From e0d8bfa229dc85b7c1550ea56a5fe5072759363f Mon Sep 17 00:00:00 2001 From: panteliselef Date: Thu, 10 Aug 2023 21:12:25 +0300 Subject: [PATCH 1/5] feat(clerk-js): Add list of suggestions in OrganizationSwitcher --- .../OrganizationSwitcher.tsx | 6 + .../OtherOrganizationActions.tsx | 2 + .../UserSuggestionList.tsx | 153 ++++++++++++++++++ packages/localizations/src/en-US.ts | 3 + packages/types/src/localization.ts | 3 + 5 files changed, 167 insertions(+) create mode 100644 packages/clerk-js/src/ui/components/OrganizationSwitcher/UserSuggestionList.tsx diff --git a/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcher.tsx b/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcher.tsx index b3187127360..f959c37f0c9 100644 --- a/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcher.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationSwitcher/OrganizationSwitcher.tsx @@ -12,10 +12,16 @@ const _OrganizationSwitcher = withFloatingTree(() => { offset: 8, }); + /** + * Prefetch user invitations and suggestions + */ useCoreOrganizationList({ userInvitations: { infinite: true, }, + userSuggestions: { + infinite: true, + }, }); return ( diff --git a/packages/clerk-js/src/ui/components/OrganizationSwitcher/OtherOrganizationActions.tsx b/packages/clerk-js/src/ui/components/OrganizationSwitcher/OtherOrganizationActions.tsx index 1acae816509..172f0b8b9f6 100644 --- a/packages/clerk-js/src/ui/components/OrganizationSwitcher/OtherOrganizationActions.tsx +++ b/packages/clerk-js/src/ui/components/OrganizationSwitcher/OtherOrganizationActions.tsx @@ -7,6 +7,7 @@ import { Action, SecondaryActions } from '../../elements'; import { UserInvitationList } from './UserInvitationList'; import type { UserMembershipListProps } from './UserMembershipList'; import { UserMembershipList } from './UserMembershipList'; +import { UserSuggestionList } from './UserSuggestionList'; export interface OrganizationActionListProps extends UserMembershipListProps { onCreateOrganizationClick: React.MouseEventHandler; @@ -45,6 +46,7 @@ export const OrganizationActionList = (props: OrganizationActionListProps) => { + ); diff --git a/packages/clerk-js/src/ui/components/OrganizationSwitcher/UserSuggestionList.tsx b/packages/clerk-js/src/ui/components/OrganizationSwitcher/UserSuggestionList.tsx new file mode 100644 index 00000000000..0a685e534f5 --- /dev/null +++ b/packages/clerk-js/src/ui/components/OrganizationSwitcher/UserSuggestionList.tsx @@ -0,0 +1,153 @@ +import type { OrganizationSuggestionResource } from '@clerk/types'; + +import { useCoreOrganizationList } from '../../contexts'; +import { Box, Button, descriptors, Flex, localizationKeys, Spinner, Text } from '../../customizables'; +import { OrganizationPreview, useCardState, withCardStateProvider } from '../../elements'; +import { useInView } from '../../hooks'; +import { common } from '../../styledSystem'; +import { handleError } from '../../utils'; + +export const UserSuggestionList = () => { + const { userSuggestions } = useCoreOrganizationList({ + userSuggestions: { + infinite: true, + }, + }); + + const { ref } = useInView({ + threshold: 0, + onChange: inView => { + if (inView) { + userSuggestions.fetchNext?.(); + } + }, + }); + + if ((userSuggestions.count ?? 0) === 0) { + return null; + } + + return ( + + ({ + minHeight: 'unset', + height: t.space.$12, + padding: `${t.space.$3} ${t.space.$6}`, + display: 'flex', + alignItems: 'center', + })} + // Handle plurals + localizationKey={localizationKeys( + (userSuggestions.count ?? 0) > 1 + ? 'organizationSwitcher.suggestionCountLabel_many' + : 'organizationSwitcher.suggestionCountLabel_single', + { + count: userSuggestions.count, + }, + )} + /> + ({ + maxHeight: `calc(4 * ${t.sizes.$12})`, + overflowY: 'auto', + ...common.unstyledScrollbar(t), + })} + > + {userSuggestions?.data?.map(inv => { + return ( + + ); + })} + + {(userSuggestions.hasNextPage || userSuggestions.isFetching) && ( + ({ + width: '100%', + height: t.space.$12, + position: 'relative', + })} + > + + + + + )} + + + ); +}; + +const AcceptRejectSuggestionButtons = (props: OrganizationSuggestionResource) => { + const card = useCardState(); + const { userSuggestions } = useCoreOrganizationList({ + userSuggestions: { + infinite: true, + }, + }); + + const mutateSwrState = () => { + (userSuggestions as any)?.unstable__mutate?.(); + }; + + const handleAccept = () => { + return card + .runAsync(props.accept()) + .then(mutateSwrState) + .catch(err => handleError(err, [], card.setError)); + }; + + return ( +