Skip to content

Commit c96f964

Browse files
committed
Extract force-an-org flow to separate component
1 parent 888771e commit c96f964

File tree

1 file changed

+102
-42
lines changed

1 file changed

+102
-42
lines changed

packages/clerk-js/src/ui/components/OrganizationList/OrganizationListPage.tsx

Lines changed: 102 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { useOrganizationList, useSessionContext, useUser } from '@clerk/shared/react';
1+
import { useOrganizationList, useUser } from '@clerk/shared/react';
2+
import type { PropsWithChildren } from 'react';
23
import { useContext, useState } from 'react';
34

45
import { Action, Actions } from '@/ui/elements/Actions';
@@ -77,47 +78,45 @@ const CreateOrganizationButton = ({
7778
};
7879

7980
export const OrganizationListPage = withCardStateProvider(() => {
80-
const card = useCardState();
8181
const { userMemberships, userSuggestions, userInvitations } = useOrganizationListInView();
8282
const isLoading = userMemberships?.isLoading || userInvitations?.isLoading || userSuggestions?.isLoading;
8383
const hasAnyData = !!(userMemberships?.count || userInvitations?.count || userSuggestions?.count);
8484

8585
const { hidePersonal } = useOrganizationListContext();
8686

87+
const sessionTasksContext = useContext(SessionTasksContext);
88+
if (sessionTasksContext) {
89+
return <ForceOrganizationSelectionFlow />;
90+
}
91+
8792
return (
88-
<Card.Root>
89-
<Card.Content sx={t => ({ padding: `${t.space.$8} ${t.space.$none} ${t.space.$none}` })}>
90-
<Card.Alert sx={t => ({ margin: `${t.space.$none} ${t.space.$5}` })}>{card.error}</Card.Alert>
91-
{isLoading && (
92-
<Flex
93-
direction={'row'}
94-
align={'center'}
95-
justify={'center'}
96-
sx={t => ({
97-
height: '100%',
98-
minHeight: t.sizes.$60,
99-
})}
100-
>
101-
<Spinner
102-
size={'lg'}
103-
colorScheme={'primary'}
104-
elementDescriptor={descriptors.spinner}
105-
/>
106-
</Flex>
107-
)}
108-
109-
{!isLoading && <OrganizationListFlows showListInitially={!(hidePersonal && !hasAnyData)} />}
110-
</Card.Content>
111-
<Card.Footer />
112-
</Card.Root>
93+
<FlowCard>
94+
{isLoading && (
95+
<Flex
96+
direction={'row'}
97+
align={'center'}
98+
justify={'center'}
99+
sx={t => ({
100+
height: '100%',
101+
minHeight: t.sizes.$60,
102+
})}
103+
>
104+
<Spinner
105+
size={'lg'}
106+
colorScheme={'primary'}
107+
elementDescriptor={descriptors.spinner}
108+
/>
109+
</Flex>
110+
)}
111+
112+
{!isLoading && <OrganizationListFlows showListInitially={!(hidePersonal && !hasAnyData)} />}
113+
</FlowCard>
113114
);
114115
});
115116

116117
const OrganizationListFlows = ({ showListInitially }: { showListInitially: boolean }) => {
117118
const { navigateAfterCreateOrganization, skipInvitationScreen, hideSlug } = useOrganizationListContext();
118119
const [isCreateOrganizationFlow, setCreateOrganizationFlow] = useState(!showListInitially);
119-
const sessionTasksContext = useContext(SessionTasksContext);
120-
const session = useSessionContext();
121120

122121
return (
123122
<>
@@ -133,22 +132,10 @@ const OrganizationListFlows = ({ showListInitially }: { showListInitially: boole
133132
>
134133
<CreateOrganizationForm
135134
flow='organizationList'
136-
onComplete={sessionTasksContext?.nextTask}
137135
startPage={{ headerTitle: localizationKeys('organizationList.createOrganization') }}
138136
skipInvitationScreen={skipInvitationScreen}
139137
navigateAfterCreateOrganization={org =>
140-
navigateAfterCreateOrganization(org).then(() => {
141-
const isForceOrganizationSelectionFlow = sessionTasksContext && session?.currentTask.key === 'org';
142-
143-
// During a force organization selection flow, keep displaying the creation form in a loading state
144-
// rather than showing the organization list. This allows the client-side navigation to complete
145-
// before transitioning away from this view.
146-
if (isForceOrganizationSelectionFlow) {
147-
return;
148-
}
149-
150-
setCreateOrganizationFlow(false);
151-
})
138+
navigateAfterCreateOrganization(org).then(() => setCreateOrganizationFlow(false))
152139
}
153140
onCancel={
154141
showListInitially && isCreateOrganizationFlow ? () => setCreateOrganizationFlow(false) : undefined
@@ -240,3 +227,76 @@ const OrganizationListPageList = (props: { onCreateOrganizationClick: () => void
240227
</>
241228
);
242229
};
230+
231+
const ForceOrganizationSelectionFlow = () => {
232+
const sessionTasksContext = useContext(SessionTasksContext);
233+
const { navigateAfterCreateOrganization, hideSlug } = useOrganizationListContext();
234+
const { userMemberships, userSuggestions, userInvitations } = useOrganizationListInView();
235+
236+
const [isNavigating, setIsNavigating] = useState(false);
237+
const isLoading = isNavigating || !!(userMemberships?.count || userInvitations?.count || userSuggestions?.count);
238+
239+
const [isCreateOrganizationFlow, setIsCreateOrganizationFlow] = useState(!userMemberships?.data?.length);
240+
241+
if (isLoading) {
242+
return (
243+
<FlowCard>
244+
<Flex
245+
direction={'row'}
246+
align={'center'}
247+
justify={'center'}
248+
sx={t => ({
249+
height: '100%',
250+
minHeight: t.sizes.$60,
251+
})}
252+
>
253+
<Spinner
254+
size={'lg'}
255+
colorScheme={'primary'}
256+
elementDescriptor={descriptors.spinner}
257+
/>
258+
</Flex>
259+
</FlowCard>
260+
);
261+
}
262+
263+
return (
264+
<FlowCard>
265+
{isCreateOrganizationFlow ? (
266+
<Box
267+
sx={t => ({
268+
padding: `${t.space.$none} ${t.space.$5} ${t.space.$5}`,
269+
})}
270+
>
271+
<CreateOrganizationForm
272+
flow='organizationList'
273+
onComplete={sessionTasksContext?.nextTask}
274+
startPage={{ headerTitle: localizationKeys('organizationList.createOrganization') }}
275+
skipInvitationScreen
276+
navigateAfterCreateOrganization={org => {
277+
setIsNavigating(true);
278+
return navigateAfterCreateOrganization(org);
279+
}}
280+
hideSlug={hideSlug}
281+
/>
282+
</Box>
283+
) : (
284+
<OrganizationListPageList onCreateOrganizationClick={() => setIsCreateOrganizationFlow(true)} />
285+
)}
286+
</FlowCard>
287+
);
288+
};
289+
290+
const FlowCard = ({ children }: PropsWithChildren) => {
291+
const card = useCardState();
292+
293+
return (
294+
<Card.Root>
295+
<Card.Content sx={t => ({ padding: `${t.space.$8} ${t.space.$none} ${t.space.$none}` })}>
296+
<Card.Alert sx={t => ({ margin: `${t.space.$none} ${t.space.$5}` })}>{card.error}</Card.Alert>
297+
{children}
298+
</Card.Content>
299+
<Card.Footer />
300+
</Card.Root>
301+
);
302+
};

0 commit comments

Comments
 (0)