diff --git a/src/components/SidenavWrapper.tsx b/src/components/SidenavWrapper.tsx index 656384cf8..c30d5ea4e 100644 --- a/src/components/SidenavWrapper.tsx +++ b/src/components/SidenavWrapper.tsx @@ -9,7 +9,6 @@ import { Sidenav } from '@internxt/ui'; import { useTranslationContext } from 'app/i18n/provider/TranslationProvider'; import { useTranslation } from 'react-i18next'; import { useAppDispatch, useAppSelector } from 'app/store/hooks'; -import workspacesSelectors from 'app/store/slices/workspaces/workspaces.selectors'; import { HUNDRED_TB } from 'app/core/constants'; import { sharedThunks } from 'app/store/slices/sharedLinks'; import logo from 'assets/icons/small-logo.svg'; @@ -22,6 +21,8 @@ import { uiActions } from 'app/store/slices/ui'; import ReferralBanner from './ReferralBanner'; import referralService from 'services/referral.service'; import { useSidenavCollapsed } from 'hooks/useSidenavCollapsed'; +import { useSelector } from 'react-redux'; +import { parsePendingWorkspaces, parseWorkspaces } from 'utils/workspaces/parseWorkspaces.utils'; const SidenavPrimaryAction = ({ user, @@ -52,9 +53,13 @@ const SidenavWrapper = () => { const isLoadingBusinessLimitAndUsage = useAppSelector( (state: RootState) => state.plan.isLoadingBusinessLimitAndUsage, ); - const workspaces = useAppSelector((state: RootState) => state.workspaces.workspaces); - const isWorkspaceDropdownAvailable = workspaces.length > 0; - const selectedWorkspace = useAppSelector(workspacesSelectors.getSelectedWorkspace); + const workspaces = useSelector((state: RootState) => state.workspaces.workspaces); + const selectedWorkspace = useSelector((state: RootState) => state.workspaces.selectedWorkspace); + const pendingWorkspaces = useSelector((state: RootState) => state.workspaces.pendingWorkspaces); + const parsedWorkspaces = parseWorkspaces(workspaces); + const parsedPendingWorkspaces = parsePendingWorkspaces(pendingWorkspaces); + const allParsedWorkspaces = [...parsedWorkspaces, ...parsedPendingWorkspaces]; + const isWorkspaceDropdownAvailable = allParsedWorkspaces.length > 0; const workspaceUuid = selectedWorkspace?.workspaceUser.workspaceId; const { itemsNavigation } = useSidenavNavigation(); const { suiteArray } = useSuiteLauncher(); diff --git a/src/utils/workspaces/parseWorkspaces.utils.test.ts b/src/utils/workspaces/parseWorkspaces.utils.test.ts new file mode 100644 index 000000000..58657337e --- /dev/null +++ b/src/utils/workspaces/parseWorkspaces.utils.test.ts @@ -0,0 +1,95 @@ +import { PendingWorkspace, WorkspaceData } from '@internxt/sdk/dist/workspaces'; +import { describe, expect, test } from 'vitest'; +import { parsePendingWorkspaces, parseWorkspaces } from './parseWorkspaces.utils'; + +const buildWorkspaceData = (overrides?: Partial): WorkspaceData => ({ + workspace: { + id: 'workspace-uuid', + name: 'Test Workspace', + avatar: 'https://example.com/avatar.png', + ...overrides, + } as WorkspaceData['workspace'], + workspaceUser: {} as WorkspaceData['workspaceUser'], +}); + +const buildPendingWorkspace = (overrides?: Partial): PendingWorkspace => + ({ + id: 'pending-uuid', + name: 'Pending Workspace', + ...overrides, + }) as PendingWorkspace; + +describe('Parsing Workspaces', () => { + test('When given a list of workspaces, then maps them to Workspace shape correctly', () => { + const input = [buildWorkspaceData()]; + const result = parseWorkspaces(input); + + expect(result).toEqual([ + { + name: 'Test Workspace', + uuid: 'workspace-uuid', + type: 'Business', + avatar: 'https://example.com/avatar.png', + }, + ]); + }); + + test('When given multiple workspaces, then all are mapped', () => { + const input = [buildWorkspaceData({ id: 'id-1', name: 'WS 1' }), buildWorkspaceData({ id: 'id-2', name: 'WS 2' })]; + const result = parseWorkspaces(input); + + expect(result).toHaveLength(2); + expect(result[0].uuid).toBe('id-1'); + expect(result[1].uuid).toBe('id-2'); + }); + + test('When given an empty array, then returns an empty array', () => { + const result = parseWorkspaces([]); + expect(result).toEqual([]); + }); + + test('When mapping, then type is always Business', () => { + const result = parseWorkspaces([buildWorkspaceData()]); + expect(result[0].type).toBe('Business'); + }); +}); + +describe('Parsing Pending Workspaces', () => { + test('When given a list of pending workspaces, then maps them to Workspace shape correctly', () => { + const input = [buildPendingWorkspace()]; + const result = parsePendingWorkspaces(input); + + expect(result).toEqual([ + { + name: 'Pending Workspace', + uuid: 'pending-uuid', + type: 'Business', + isPending: true, + avatar: null, + }, + ]); + }); + + test('When given multiple pending workspaces, then all are mapped', () => { + const input = [ + buildPendingWorkspace({ id: 'p-1', name: 'Pending 1' }), + buildPendingWorkspace({ id: 'p-2', name: 'Pending 2' }), + ]; + const result = parsePendingWorkspaces(input); + + expect(result).toHaveLength(2); + expect(result[0].uuid).toBe('p-1'); + expect(result[1].uuid).toBe('p-2'); + }); + + test('When given an empty array, then returns an empty array', () => { + const result = parsePendingWorkspaces([]); + expect(result).toEqual([]); + }); + + test('When mapping, then all should be marked as pending', () => { + const result = parsePendingWorkspaces([buildPendingWorkspace()]); + expect(result[0].isPending).toBe(true); + expect(result[0].avatar).toBeNull(); + }); +}); diff --git a/src/utils/workspaces/parseWorkspaces.utils.ts b/src/utils/workspaces/parseWorkspaces.utils.ts new file mode 100644 index 000000000..1f11831bc --- /dev/null +++ b/src/utils/workspaces/parseWorkspaces.utils.ts @@ -0,0 +1,23 @@ +import { PendingWorkspace, WorkspaceData } from '@internxt/sdk/dist/workspaces'; +import { Workspace } from 'views/Home/components/WorkspaceSelector'; + +export const parseWorkspaces = (workspaces: WorkspaceData[]): Workspace[] => + workspaces?.map((workspace) => { + return { + name: workspace.workspace.name, + uuid: workspace.workspace.id, + type: 'Business', + avatar: workspace.workspace.avatar, + }; + }); + +export const parsePendingWorkspaces = (workspaces: PendingWorkspace[]): Workspace[] => + workspaces?.map((workspace) => { + return { + name: workspace.name, + uuid: workspace.id, + type: 'Business', + isPending: true, + avatar: null, + }; + });