diff --git a/src/components/ShareOptions/ShareOptionsModal.tsx b/src/components/ShareOptions/ShareOptionsModal.tsx index 8ed886e9e..8c9e1241c 100644 --- a/src/components/ShareOptions/ShareOptionsModal.tsx +++ b/src/components/ShareOptions/ShareOptionsModal.tsx @@ -1,4 +1,4 @@ -import { type ReactNode, useCallback, useState } from 'react'; +import { type ReactNode, useCallback, useState, useMemo } from 'react'; import { Globe2, Loader2, Lock } from 'lucide-react'; import { type ListFriendsResponse, ShareFriendList } from './ShareFriendList'; import { TransferToTeamList } from './TransferToTeamList'; @@ -49,7 +49,10 @@ export function ShareOptionsModal(props: ShareOptionsModalProps) { const [isSettingsUpdated, setIsSettingsUpdated] = useState(false); const [friends, setFriends] = useState([]); const [teams, setTeams] = useState([]); - const [members, setMembers] = useState([]); + + // Using global team members loading state to avoid glitchy UI when switching between teams + const [isTeamMembersLoading, setIsTeamMembersLoading] = useState(false); + const membersCache = useMemo(() => new Map(), []); const [visibility, setVisibility] = useState(defaultVisibility); const [sharedTeamMemberIds, setSharedTeamMemberIds] = useState( @@ -118,7 +121,7 @@ export function ShareOptionsModal(props: ShareOptionsModalProps) { }; const handleTransferToTeam = useCallback( - async (teamId: string) => { + async (teamId: string, sharedTeamMemberIds: string[]) => { if (!roadmapId) { return; } @@ -128,6 +131,7 @@ export function ShareOptionsModal(props: ShareOptionsModalProps) { `${import.meta.env.PUBLIC_API_URL}/v1-transfer-roadmap/${roadmapId}`, { teamId, + sharedTeamMemberIds, } ); @@ -187,6 +191,7 @@ export function ShareOptionsModal(props: ShareOptionsModalProps) { defaultSharedFriendIds.length > 0 ? defaultSharedFriendIds : [] ); } else if (visibility === 'team' && teamId) { + setIsTeamMembersLoading(true); setSharedTeamMemberIds( defaultSharedMemberIds?.length > 0 ? defaultSharedMemberIds : [] ); @@ -225,14 +230,6 @@ export function ShareOptionsModal(props: ShareOptionsModalProps) { setSharedFriendIds={setSharedFriendIds} /> )} - {canTransferRoadmap && ( - - )} {/* For Team Roadmap */} {visibility === 'team' && teamId && ( @@ -240,10 +237,44 @@ export function ShareOptionsModal(props: ShareOptionsModalProps) { teamId={teamId} sharedTeamMemberIds={sharedTeamMemberIds} setSharedTeamMemberIds={setSharedTeamMemberIds} - members={members} - setMembers={setMembers} + membersCache={membersCache} + isTeamMembersLoading={isTeamMembersLoading} + setIsTeamMembersLoading={setIsTeamMembersLoading} /> )} + + {canTransferRoadmap && ( + <> + { + setIsTeamMembersLoading(true); + setSharedTeamMemberIds([]); + }} + /> + {selectedTeamId && ( + <> +
+
+ +
+ + )} + + )}
@@ -255,17 +286,23 @@ export function ShareOptionsModal(props: ShareOptionsModalProps) { Close - {canTransferRoadmap ? ( + {canTransferRoadmap && ( { - handleTransferToTeam(selectedTeamId!).then(() => null); + handleTransferToTeam(selectedTeamId!, sharedTeamMemberIds).then( + () => null + ); }} > {isLoading && } Transfer - ) : ( + )} + + {!canTransferRoadmap && ( { diff --git a/src/components/ShareOptions/ShareTeamMemberList.tsx b/src/components/ShareOptions/ShareTeamMemberList.tsx index 6eaf54003..d23145fb6 100644 --- a/src/components/ShareOptions/ShareTeamMemberList.tsx +++ b/src/components/ShareOptions/ShareTeamMemberList.tsx @@ -33,27 +33,31 @@ export interface TeamMemberList extends TeamMemberDocument { type ShareTeamMemberListProps = { teamId: string; - setMembers: (members: TeamMemberList[]) => void; - members: TeamMemberList[]; + title?: string; sharedTeamMemberIds: string[]; setSharedTeamMemberIds: (sharedTeamMemberIds: string[]) => void; + + membersCache: Map; + isTeamMembersLoading: boolean; + setIsTeamMembersLoading: (isLoading: boolean) => void; }; export function ShareTeamMemberList(props: ShareTeamMemberListProps) { const { - setMembers, - members, + teamId, + title = 'Select Members', sharedTeamMemberIds, setSharedTeamMemberIds, - teamId, + + membersCache, + isTeamMembersLoading: isLoading, + setIsTeamMembersLoading: setIsLoading, } = props; const toast = useToast(); - const [isLoading, setIsLoading] = useState(true); - async function loadTeamMembers() { - if (members?.length > 0) { + if (membersCache.has(teamId)) { return; } @@ -67,21 +71,21 @@ export function ShareTeamMemberList(props: ShareTeamMemberListProps) { return; } - setMembers(response); + membersCache.set(teamId, response); } useEffect(() => { loadTeamMembers().finally(() => { setIsLoading(false); }); - }, []); + }, [teamId]); const loadingMembers = isLoading && (
    {[...Array(3)].map((_, idx) => (
  • @@ -93,11 +97,13 @@ export function ShareTeamMemberList(props: ShareTeamMemberListProps) {
); + const members = membersCache.get(teamId) || []; + return ( <> {(members.length > 0 || isLoading) && (
-

Select Members

+

{title}