diff --git a/src/frontend/apps/desk/src/features/teams/api/useCreateTeam.tsx b/src/frontend/apps/desk/src/features/teams/api/useCreateTeam.tsx index c06da69..384ce73 100644 --- a/src/frontend/apps/desk/src/features/teams/api/useCreateTeam.tsx +++ b/src/frontend/apps/desk/src/features/teams/api/useCreateTeam.tsx @@ -12,7 +12,7 @@ export interface CreateTeamResponseError { detail: string; } -export const createTeam = async (name: string) => { +export const createTeam = async (name: string): Promise => { const response = await fetchAPI(`teams/`, { method: 'POST', body: JSON.stringify({ @@ -24,17 +24,22 @@ export const createTeam = async (name: string) => { throw new Error(`Couldn't create team: ${response.statusText}`); } - return response.json(); + return response.json() as Promise; }; -export function useCreateTeam() { +interface CreateTeamProps { + onSuccess: (data: CreateTeamResponse) => void; +} + +export function useCreateTeam({ onSuccess }: CreateTeamProps) { const queryClient = useQueryClient(); return useMutation({ mutationFn: createTeam, - onSuccess: () => { + onSuccess: (data) => { void queryClient.invalidateQueries({ queryKey: [KEY_LIST_TEAM], }); + onSuccess(data); }, }); } diff --git a/src/frontend/apps/desk/src/features/teams/components/PanelTeam.tsx b/src/frontend/apps/desk/src/features/teams/components/PanelTeam.tsx index 6fb239f..689040f 100644 --- a/src/frontend/apps/desk/src/features/teams/components/PanelTeam.tsx +++ b/src/frontend/apps/desk/src/features/teams/components/PanelTeam.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import IconGroup from '@/assets/icons/icon-group.svg'; -import { Box, Text } from '@/components'; +import { Box, StyledLink, Text } from '@/components'; import { useCunninghamTheme } from '@/cunningham'; -import { TeamResponse } from '../api/useTeams'; +import { TeamResponse } from '../api/types'; import IconNone from '../assets/icon-none.svg'; interface TeamProps { @@ -29,29 +29,33 @@ export const PanelTeam = ({ team }: TeamProps) => { }; return ( - - {hasMembers ? ( - - ) : ( - - )} - {team.name} + + + + {hasMembers ? ( + + ) : ( + + )} + {team.name} + + ); }; diff --git a/src/frontend/apps/desk/src/pages/teams/[id].tsx b/src/frontend/apps/desk/src/pages/teams/[id].tsx new file mode 100644 index 0000000..8347ac2 --- /dev/null +++ b/src/frontend/apps/desk/src/pages/teams/[id].tsx @@ -0,0 +1,65 @@ +import { Loader } from '@openfun/cunningham-react'; +import { useRouter } from 'next/router'; +import { ReactElement } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { Box, Text } from '@/components'; +import { useTeam } from '@/features/teams/api/useTeam'; +import { NextPageWithLayout } from '@/types/next'; + +import TeamLayout from './TeamLayout'; + +const Page: NextPageWithLayout = () => { + const { + query: { id }, + } = useRouter(); + + if (typeof id !== 'string') { + throw new Error('Invalid team id'); + } + + return ; +}; + +interface TeamProps { + id: string; +} + +const Team = ({ id }: TeamProps) => { + const { t } = useTranslation(); + const { data: team, isLoading, isError } = useTeam({ id }); + + if (isError) { + return ( + + {t('Something bad happens, please retry.')} + + ); + } + + if (isLoading) { + return ( + + + + ); + } + + return ( + + Teams: {team?.name} + + ); +}; + +Page.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export default Page; diff --git a/src/frontend/apps/desk/src/pages/teams/create.tsx b/src/frontend/apps/desk/src/pages/teams/create.tsx index 4ed3312..b000fab 100644 --- a/src/frontend/apps/desk/src/pages/teams/create.tsx +++ b/src/frontend/apps/desk/src/pages/teams/create.tsx @@ -1,4 +1,5 @@ import { Button, Input, Loader } from '@openfun/cunningham-react'; +import { useRouter } from 'next/navigation'; import { ReactElement, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -12,7 +13,16 @@ import TeamLayout from './TeamLayout'; const Page: NextPageWithLayout = () => { const { t } = useTranslation(); - const { mutate: createTeam, isError, isPending } = useCreateTeam(); + const router = useRouter(); + const { + mutate: createTeam, + isError, + isPending, + } = useCreateTeam({ + onSuccess: (team) => { + router.push(`/teams/${team.id}`); + }, + }); const [teamName, setTeamName] = useState(''); const { colorsTokens } = useCunninghamTheme(); diff --git a/src/frontend/apps/e2e/__tests__/app-desk/teams-create.spec.ts b/src/frontend/apps/e2e/__tests__/app-desk/teams-create.spec.ts index 48a469a..934a053 100644 --- a/src/frontend/apps/e2e/__tests__/app-desk/teams-create.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-desk/teams-create.spec.ts @@ -58,4 +58,26 @@ test.describe('Teams', () => { await expect(buttonCreateHomepage).toBeVisible(); }); + + test('checks the routing on new team created', async ({ + page, + browserName, + }) => { + const panel = page.getByLabel('Teams panel').first(); + + await panel.getByRole('button', { name: 'Add a team' }).click(); + + const teamName = `My routing team ${browserName}-${Math.floor(Math.random() * 1000)}`; + await page.getByText('Team name').fill(teamName); + await page.getByRole('button', { name: 'Create the team' }).click(); + + const elTeam = page.getByText(`Teams: ${teamName}`); + await expect(elTeam).toBeVisible(); + + await panel.getByRole('button', { name: 'Add a team' }).click(); + await expect(elTeam).toBeHidden(); + + await panel.locator('li').getByText(teamName).click(); + await expect(elTeam).toBeVisible(); + }); }); diff --git a/src/frontend/apps/e2e/__tests__/app-desk/teams-panel.spec.ts b/src/frontend/apps/e2e/__tests__/app-desk/teams-panel.spec.ts index e952c0d..b61632f 100644 --- a/src/frontend/apps/e2e/__tests__/app-desk/teams-panel.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-desk/teams-panel.spec.ts @@ -27,28 +27,23 @@ test.describe('Teams Panel', () => { name: 'Add a team', }), ).toBeVisible(); - - await expect( - panel.getByText( - 'Create your first team by clicking on the "Create a new team" button.', - ), - ).toBeVisible(); }); test('002 - checks the sort button', async ({ page, browserName }) => { const panel = page.getByLabel('Teams panel').first(); - await panel.getByRole('button', { name: 'Add a team' }).click(); - - const randomTeams = Array.from({ length: 3 }, () => { - return `team-sort-${browserName}-${Math.floor(Math.random() * 1000)}`; + const buttonCreate = page.getByRole('button', { name: 'Create the team' }); + const randomTeams = Array.from({ length: 3 }, (_el, index) => { + return `team-sort-${browserName}-${Math.floor(Math.random() * 1000)}-${index}`; }); - for (let i = 0; i < 3; i++) { - await page.getByText('Team name').fill(`${randomTeams[i]}-${i}`); - await page.getByRole('button', { name: 'Create the team' }).click(); + for (let i = 0; i < randomTeams.length; i++) { + await panel.getByRole('button', { name: 'Add a team' }).click(); + await page.getByText('Team name').fill(randomTeams[i]); + await expect(buttonCreate).toBeEnabled(); + await buttonCreate.click(); await expect( - panel.locator('li').nth(0).getByText(`${randomTeams[i]}-${i}`), + panel.locator('li').nth(0).getByText(randomTeams[i]), ).toBeVisible(); } @@ -58,32 +53,33 @@ test.describe('Teams Panel', () => { }) .click(); - for (let i = 0; i < 3; i++) { - await expect( - panel.locator('li').nth(i).getByText(`${randomTeams[i]}-${i}`), - ).toBeVisible(); - } + await expect(panel.locator('li').getByText(randomTeams[1])).toBeVisible(); + + const allTeams = await panel.locator('li').allTextContents(); + const sortedTeamTexts = allTeams.filter((team) => + randomTeams.some((randomTeam) => team.includes(randomTeam)), + ); + expect(sortedTeamTexts).toStrictEqual(randomTeams); }); test('003 - checks the infinite scrool', async ({ page, browserName }) => { test.setTimeout(90000); const panel = page.getByLabel('Teams panel').first(); - await panel.getByRole('button', { name: 'Add a team' }).click(); - - const randomTeams = Array.from({ length: 40 }, () => { - return `team-infinite-${browserName}-${Math.floor(Math.random() * 10000)}`; + const buttonCreate = page.getByRole('button', { name: 'Create the team' }); + const randomTeams = Array.from({ length: 40 }, (_el, index) => { + return `team-infinite-${browserName}-${Math.floor(Math.random() * 10000)}-${index}`; }); - for (let i = 0; i < 40; i++) { - await page.getByText('Team name').fill(`${randomTeams[i]}-${i}`); - await page.getByRole('button', { name: 'Create the team' }).click(); - await expect( - panel.locator('li').getByText(`${randomTeams[i]}-${i}`), - ).toBeVisible(); + for (let i = 0; i < randomTeams.length; i++) { + await panel.getByRole('button', { name: 'Add a team' }).click(); + await page.getByText('Team name').fill(randomTeams[i]); + await expect(buttonCreate).toBeEnabled(); + await buttonCreate.click(); + await expect(panel.locator('li').getByText(randomTeams[i])).toBeVisible(); } await expect(panel.locator('li')).toHaveCount(20); - await panel.getByText(`${randomTeams[24]}-${24}`).click(); + await panel.getByText(randomTeams[24]).click(); await waitForElementCount(panel.locator('li'), 21, 10000); expect(await panel.locator('li').count()).toBeGreaterThan(20);