(app-desk) add interaction to sort button

In the team panel, we have the possibility to sort the teams.
This commit adds the interaction to the button.
This commit is contained in:
Anthony LC
2024-02-01 15:33:53 +01:00
committed by Anthony LC
parent 36e2dc2378
commit fafffd2391
10 changed files with 125 additions and 22 deletions

View File

@@ -4,3 +4,22 @@ body {
margin: 0;
padding: 0;
}
::-webkit-scrollbar {
width: 20px;
}
::-webkit-scrollbar-track {
background-color: transparent;
}
::-webkit-scrollbar-thumb {
background-color: #d6dee1;
border-radius: 20px;
border: 6px solid transparent;
background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover {
background-color: #a8bbbf;
}

View File

@@ -1,12 +1,13 @@
'use client';
import { Button } from '@openfun/cunningham-react';
import { Button, Field, Input } from '@openfun/cunningham-react';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import styled from 'styled-components';
import { Box } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { Panel } from '@/features';
import { Panel, useCreateTeam } from '@/features';
const StyledButton = styled(Button)`
width: fit-content;
@@ -14,6 +15,8 @@ const StyledButton = styled(Button)`
export default function Home() {
const { t } = useTranslation();
const { mutate: createTeam } = useCreateTeam();
const [teamName, setTeamName] = useState('');
const { colorsTokens } = useCunninghamTheme();
return (
@@ -24,8 +27,23 @@ export default function Home() {
$justify="center"
$align="center"
$width="100%"
$gap="5rem"
>
<StyledButton>{t('Create a new group')}</StyledButton>
<StyledButton>{t('Create a new team')}</StyledButton>
<Field>
<Input
type="text"
label={t('Team name')}
onChange={(e) => setTeamName(e.target.value)}
/>
<Button
fullWidth
onClick={() => createTeam(teamName)}
className="mt-s"
>
{t('Create a team')}
</Button>
</Field>
</Box>
</Box>
);

View File

@@ -0,0 +1 @@
export * from './useCreateTeam';

View File

@@ -34,7 +34,6 @@ export function useCreateTeam() {
onSuccess: () => {
void queryClient.invalidateQueries({
queryKey: [KEY_LIST_TEAM],
exact: true,
});
},
});

View File

@@ -20,13 +20,24 @@ interface TeamResponse {
accesses: Access[];
}
export enum TeamsOrdering {
BY_CREATED_ON = 'created_at',
BY_CREATED_ON_DESC = '-created_at',
}
export type TeamsParams = {
ordering?: TeamsOrdering;
};
type TeamsResponse = APIList<TeamResponse>;
export interface TeamsResponseError {
detail: string;
}
export const getTeams = async () => {
const response = await fetchAPI(`teams/`);
export const getTeams = async (props?: TeamsParams) => {
const response = await fetchAPI(
`teams/${props?.ordering ? `?ordering=${props.ordering}` : ''}`,
);
if (!response.ok) {
throw new Error(`Couldn't fetch teams: ${response.statusText}`);
@@ -37,6 +48,7 @@ export const getTeams = async () => {
export const KEY_LIST_TEAM = 'teams';
export function useTeams(
param?: TeamsParams,
queryConfig?: UseQueryOptions<
TeamsResponse,
TeamsResponseError,
@@ -44,8 +56,8 @@ export function useTeams(
>,
) {
return useQuery<TeamsResponse, TeamsResponseError, TeamsResponse>({
queryKey: [KEY_LIST_TEAM],
queryFn: getTeams,
queryKey: [KEY_LIST_TEAM, param],
queryFn: () => getTeams(param),
...queryConfig,
});
}

View File

@@ -7,9 +7,11 @@ import { Box } from '@/components';
import { default as IconAdd } from '../assets/icon-add.svg?url';
import { default as IconSort } from '../assets/icon-sort.svg?url';
import { useTeamStore } from '../store/useTeamsStore';
export const PanelActions = () => {
const { t } = useTranslation();
const changeOrdering = useTeamStore((state) => state.changeOrdering);
return (
<Box
@@ -26,6 +28,7 @@ export const PanelActions = () => {
icon={<Image priority src={IconSort} alt={t('Sort teams icon')} />}
color="tertiary"
className="c__button-no-bg p-0 m-0"
onClick={changeOrdering}
/>
<Button
aria-label={t('Add a team')}

View File

@@ -8,9 +8,13 @@ import { useCunninghamTheme } from '@/cunningham';
import { useTeams } from '../api/useTeams';
import IconNone from '../assets/icon-none.svg';
import { useTeamStore } from '../store/useTeamsStore';
export const PanelTeams = () => {
const { data, isPending, isError } = useTeams();
const ordering = useTeamStore((state) => state.ordering);
const { data, isPending, isError } = useTeams({
ordering,
});
const { t } = useTranslation();
const { colorsTokens } = useCunninghamTheme();
@@ -48,7 +52,7 @@ export const PanelTeams = () => {
}
return (
<Box as="ul" $gap="1rem" className="p-s mt-t">
<Box as="ul" $gap="1rem" className="p-s mt-t" $css="overflow:auto;">
{data?.results.map((team) => (
<Box
as="li"

View File

@@ -1 +1,2 @@
export * from './components/Panel';
export * from './components';
export * from './api';

View File

@@ -0,0 +1,19 @@
import { create } from 'zustand';
import { TeamsOrdering } from '../api/useTeams';
interface TeamsStore {
ordering: TeamsOrdering;
changeOrdering: () => void;
}
export const useTeamStore = create<TeamsStore>((set) => ({
ordering: TeamsOrdering.BY_CREATED_ON_DESC,
changeOrdering: () =>
set(({ ordering }) => ({
ordering:
ordering === TeamsOrdering.BY_CREATED_ON
? TeamsOrdering.BY_CREATED_ON_DESC
: TeamsOrdering.BY_CREATED_ON,
})),
}));

View File

@@ -1,27 +1,27 @@
import { expect, test } from "@playwright/test";
import { expect, test } from '@playwright/test';
import { keyCloakSignIn } from "./common";
import { keyCloakSignIn } from './common';
test.beforeEach(async ({ page }) => {
await page.goto("/");
await page.goto('/');
await keyCloakSignIn(page);
});
test.describe("Teams", () => {
test("checks all the elements are visible", async ({ page }) => {
const panel = page.getByLabel("Teams panel").first();
test.describe('Teams', () => {
test('checks all the elements are visible', async ({ page }) => {
const panel = page.getByLabel('Teams panel').first();
await expect(panel.getByText("Recents")).toBeVisible();
await expect(panel.getByText('Recents')).toBeVisible();
await expect(
panel.getByRole("button", {
name: "Sort the teams",
panel.getByRole('button', {
name: 'Sort the teams',
}),
).toBeVisible();
await expect(
panel.getByRole("button", {
name: "Add a team",
panel.getByRole('button', {
name: 'Add a team',
}),
).toBeVisible();
@@ -31,4 +31,31 @@ test.describe("Teams", () => {
),
).toBeVisible();
});
test('check sort button', async ({ page }) => {
const panel = page.getByLabel('Teams panel').first();
for (let i = 0; i < 3; i++) {
await page.getByText('Team name').fill(`team-sort${i}`);
await page.getByRole('button', { name: 'Create a team' }).click();
await expect(
panel.locator('li').getByText(`team-sort${i}`),
).toBeVisible();
}
await panel
.getByRole('button', {
name: 'Sort the teams',
})
.click();
for (let i = 0; i < 3; i++) {
await expect(
panel
.locator('li')
.nth(i)
.getByText(`team-sort${i + 1}`),
).toBeVisible();
}
});
});