Skip to content

Commit f1f5250

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

File tree

1 file changed

+102
-44
lines changed

1 file changed

+102
-44
lines changed

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

Lines changed: 102 additions & 44 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,23 +132,9 @@ const OrganizationListFlows = ({ showListInitially }: { showListInitially: boole
133132
>
134133
<CreateOrganizationForm
135134
flow='organizationList'
136-
onComplete={sessionTasksContext?.nextTask}
137135
startPage={{ headerTitle: localizationKeys('organizationList.createOrganization') }}
138136
skipInvitationScreen={skipInvitationScreen}
139-
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-
})
152-
}
137+
navigateAfterCreateOrganization={org => navigateAfterCreateOrganization(org)}
153138
onCancel={
154139
showListInitially && isCreateOrganizationFlow ? () => setCreateOrganizationFlow(false) : undefined
155140
}
@@ -240,3 +225,76 @@ const OrganizationListPageList = (props: { onCreateOrganizationClick: () => void
240225
</>
241226
);
242227
};
228+
229+
const ForceOrganizationSelectionFlow = () => {
230+
const sessionTasksContext = useContext(SessionTasksContext);
231+
const { navigateAfterCreateOrganization, hideSlug } = useOrganizationListContext();
232+
const { userMemberships, userSuggestions, userInvitations } = useOrganizationListInView();
233+
234+
const [isNavigating, setIsNavigating] = useState(false);
235+
const isLoading = isNavigating || !!(userMemberships?.count || userInvitations?.count || userSuggestions?.count);
236+
237+
const [isCreateOrganizationFlow, setIsCreateOrganizationFlow] = useState(!userMemberships?.data?.length);
238+
239+
if (isLoading) {
240+
return (
241+
<FlowCard>
242+
<Flex
243+
direction={'row'}
244+
align={'center'}
245+
justify={'center'}
246+
sx={t => ({
247+
height: '100%',
248+
minHeight: t.sizes.$60,
249+
})}
250+
>
251+
<Spinner
252+
size={'lg'}
253+
colorScheme={'primary'}
254+
elementDescriptor={descriptors.spinner}
255+
/>
256+
</Flex>
257+
</FlowCard>
258+
);
259+
}
260+
261+
return (
262+
<FlowCard>
263+
{isCreateOrganizationFlow ? (
264+
<Box
265+
sx={t => ({
266+
padding: `${t.space.$none} ${t.space.$5} ${t.space.$5}`,
267+
})}
268+
>
269+
<CreateOrganizationForm
270+
flow='organizationList'
271+
onComplete={sessionTasksContext?.nextTask}
272+
startPage={{ headerTitle: localizationKeys('organizationList.createOrganization') }}
273+
skipInvitationScreen
274+
navigateAfterCreateOrganization={org => {
275+
setIsNavigating(true);
276+
return navigateAfterCreateOrganization(org);
277+
}}
278+
hideSlug={hideSlug}
279+
/>
280+
</Box>
281+
) : (
282+
<OrganizationListPageList onCreateOrganizationClick={() => setIsCreateOrganizationFlow(true)} />
283+
)}
284+
</FlowCard>
285+
);
286+
};
287+
288+
const FlowCard = ({ children }: PropsWithChildren) => {
289+
const card = useCardState();
290+
291+
return (
292+
<Card.Root>
293+
<Card.Content sx={t => ({ padding: `${t.space.$8} ${t.space.$none} ${t.space.$none}` })}>
294+
<Card.Alert sx={t => ({ margin: `${t.space.$none} ${t.space.$5}` })}>{card.error}</Card.Alert>
295+
{children}
296+
</Card.Content>
297+
<Card.Footer />
298+
</Card.Root>
299+
);
300+
};

0 commit comments

Comments
 (0)