(app-desk) integrate member list design

Integrate the member list design in the team page
based on the mockup.
This commit is contained in:
Anthony LC
2024-02-29 15:59:10 +01:00
committed by Anthony LC
parent 9d30bc88f1
commit e16f51ca20
16 changed files with 334 additions and 68 deletions

View File

@@ -78,6 +78,7 @@ const config = {
'forms-labelledbox': {
'label-color': {
small: 'var(--c--theme--colors--primary-500)',
'small-disabled': 'var(--c--theme--colors--greyscale-400)',
big: {
disabled: 'var(--c--theme--colors--greyscale-400)',
},
@@ -85,6 +86,8 @@ const config = {
},
'forms-select': {
'border-color': 'var(--c--theme--colors--primary-500)',
'border-color-disabled-hover':
'var(--c--theme--colors--greyscale-200)',
'border-radius': {
hover: 'var(--c--components--forms-select--border-radius)',
focus: 'var(--c--components--forms-select--border-radius)',
@@ -199,10 +202,10 @@ const config = {
'secondary-800': '#341f1f',
'secondary-900': '#2b1919',
'greyscale-text': '#303C4B',
'greyscale-000': '#cecece',
'greyscale-100': '#f6f6f6',
'greyscale-200': '#eeeeee',
'greyscale-300': '#e5e5e5',
'greyscale-000': '#f6f6f6',
'greyscale-100': '#eeeeee',
'greyscale-200': '#e5e5e5',
'greyscale-300': '#e1e1e1',
'greyscale-400': '#dddddd',
'greyscale-500': '#cecece',
'greyscale-600': '#7b7b7b',
@@ -284,6 +287,20 @@ const config = {
color: 'var(--c--theme--colors--primary-text)',
},
},
datagrid: {
header: {
color: 'var(--c--theme--colors--primary-text)',
size: 'var(--c--theme--font--sizes--s)',
},
body: {
'background-color': 'transparent',
'background-color-hover': '#F4F4FD',
},
pagination: {
'background-color': 'transparent',
'background-color-active': 'var(--c--theme--colors--primary-300)',
},
},
'forms-checkbox': {
'border-radius': '0',
},
@@ -305,7 +322,12 @@ const config = {
},
},
'forms-select': {
'border-radius': '0',
'border-radius': '4px',
'border-radius-hover': '4px',
'background-color': '#ffffff',
'border-color': 'var(--c--theme--colors--primary-text)',
'border-color-hover': 'var(--c--theme--colors--primary-text)',
'box-shadow-color': 'var(--c--theme--colors--primary-text)',
},
'forms-switch': {
'handle-border-radius': '2px',

View File

@@ -0,0 +1,6 @@
<svg viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M20 0C8.96 0 0 8.96 0 20C0 31.04 8.96 40 20 40C31.04 40 40 31.04 40 20C40 8.96 31.04 0 20 0ZM20 6C23.32 6 26 8.68 26 12C26 15.32 23.32 18 20 18C16.68 18 14 15.32 14 12C14 8.68 16.68 6 20 6ZM20 34.4C15 34.4 10.58 31.84 8 27.96C8.06 23.98 16 21.8 20 21.8C23.98 21.8 31.94 23.98 32 27.96C29.42 31.84 25 34.4 20 34.4Z"
fill="currentColor"
/>
</svg>

After

Width:  |  Height:  |  Size: 439 B

View File

@@ -14,6 +14,7 @@ export interface BoxProps {
$gap?: CSSProperties['gap'];
$height?: CSSProperties['height'];
$justify?: CSSProperties['justifyContent'];
$overflow?: CSSProperties['overflow'];
$position?: CSSProperties['position'];
$radius?: CSSProperties['borderRadius'];
$width?: CSSProperties['width'];
@@ -35,6 +36,7 @@ export const Box = styled('div')<BoxProps>`
${({ $gap }) => $gap && `gap: ${$gap};`}
${({ $height }) => $height && `height: ${$height};`}
${({ $justify }) => $justify && `justify-content: ${$justify};`}
${({ $overflow }) => $overflow && `overflow: ${$overflow};`}
${({ $position }) => $position && `position: ${$position};`}
${({ $radius }) => $radius && `border-radius: ${$radius};`}
${({ $width }) => $width && `width: ${$width};`}

View File

@@ -1,4 +1,5 @@
export * from './Box';
export * from './Text';
export * from './Link';
export * from './TextErrors';
export * from './Card';

View File

@@ -21,7 +21,7 @@
}
.labelled-box--disabled label {
color: var(--c--components--forms-labelledbox--label-color--small--disabled);
color: var(--c--components--forms-labelledbox--label-color--small-disabled);
}
.c__field :not(.c__textarea__wrapper, div) .labelled-box label.placeholder {
@@ -120,7 +120,16 @@ input:-webkit-autofill:focus {
}
.c__select:not(.c__select--disabled) .c__select__wrapper:hover {
box-shadow: var(--c--theme--colors--primary-500) 0 0 0 2px;
box-shadow: var(--c--components--forms-input--box-shadow-color) 0 0 0 2px;
}
.c__select__wrapper:hover {
border-radius: var(--c--components--forms-select--border-radius-hover);
border-color: var(--c--components--forms-select--border-color-hover);
}
.c__select--disabled .c__select__wrapper:hover {
border-color: var(--c--components--forms-select--border-color-disabled-hover);
}
.c__select__menu__item {
@@ -135,7 +144,7 @@ input:-webkit-autofill:focus {
}
.c__select__wrapper:focus-within .labelled-box--disabled label {
color: var(--c--components--forms-labelledbox--label-color--small--disabled);
color: var(--c--components--forms-labelledbox--label-color--small-disabled);
}
.c__select__wrapper .labelled-box {
@@ -173,28 +182,60 @@ input:-webkit-autofill:focus {
/**
* DataGrid
*/
.c__datagrid > table td {
max-width: 10rem;
white-space: normal;
color: var(--c--components--datagrid--cell--color);
font-size: var(--c--components--datagrid--cell--size);
.c__datagrid__table__container {
overflow: auto;
}
.c__datagrid > table th .c__datagrid__header {
color: var(--c--theme--colors--primary-500);
.c__datagrid__table__container > table th .c__datagrid__header {
color: var(--c--components--datagrid--header--color);
font-weight: var(--c--components--datagrid--header--weight);
font-size: var(--c--components--datagrid--header--size);
padding-block: 2rem;
}
.c__datagrid > table tbody tr {
border: 1px var(--c--theme--colors--primary-100) solid;
.c__datagrid__table__container > table tbody tr {
border: none;
border-top: 1px var(--c--theme--colors--greyscale-300) solid;
border-bottom: 1px var(--c--theme--colors--greyscale-300) solid;
}
.c__datagrid__table__container > table tbody {
background-color: var(--c--components--datagrid--body--background-color);
}
.c__datagrid__table__container > table tbody tr:hover {
background-color: var(
--c--components--datagrid--body--background-color-hover
);
}
.c__datagrid__table__container > table th:first-child,
.c__datagrid__table__container > table td:first-child {
padding-left: 2rem;
}
.c__datagrid > .c__pagination {
padding-top: 1rem;
padding-right: 1rem;
justify-content: flex-end;
}
.c__pagination__list {
gap: 3px;
border-radius: 4px;
background: var(--c--components--datagrid--pagination--background-color);
}
.c__pagination__list .c__button--tertiary.c__button--active {
background-color: var(
--c--components--datagrid--pagination--background-color-active
);
color: var(--c--theme--colors--greyscale-800);
}
.c__pagination__list .c__button--tertiary:disabled {
display: none;
}
@media (width <= 380px) {
.c__datagrid > .c__pagination {
flex-direction: column;

View File

@@ -160,12 +160,18 @@
--c--components--forms-labelledbox--label-color--small: var(
--c--theme--colors--primary-500
);
--c--components--forms-labelledbox--label-color--small-disabled: var(
--c--theme--colors--greyscale-400
);
--c--components--forms-labelledbox--label-color--big--disabled: var(
--c--theme--colors--greyscale-400
);
--c--components--forms-select--border-color: var(
--c--theme--colors--primary-500
);
--c--components--forms-select--border-color-disabled-hover: var(
--c--theme--colors--greyscale-200
);
--c--components--forms-select--border-radius--hover: var(
--c--components--forms-select--border-radius
);
@@ -337,10 +343,10 @@
--c--theme--colors--secondary-800: #341f1f;
--c--theme--colors--secondary-900: #2b1919;
--c--theme--colors--greyscale-text: #303c4b;
--c--theme--colors--greyscale-000: #cecece;
--c--theme--colors--greyscale-100: #f6f6f6;
--c--theme--colors--greyscale-200: #eee;
--c--theme--colors--greyscale-300: #e5e5e5;
--c--theme--colors--greyscale-000: #f6f6f6;
--c--theme--colors--greyscale-100: #eee;
--c--theme--colors--greyscale-200: #e5e5e5;
--c--theme--colors--greyscale-300: #e1e1e1;
--c--theme--colors--greyscale-400: #ddd;
--c--theme--colors--greyscale-500: #cecece;
--c--theme--colors--greyscale-600: #7b7b7b;
@@ -415,6 +421,16 @@
--c--components--button--secondary--color: var(
--c--theme--colors--primary-text
);
--c--components--datagrid--header--color: var(
--c--theme--colors--primary-text
);
--c--components--datagrid--header--size: var(--c--theme--font--sizes--s);
--c--components--datagrid--body--background-color: transparent;
--c--components--datagrid--body--background-color-hover: #f4f4fd;
--c--components--datagrid--pagination--background-color: transparent;
--c--components--datagrid--pagination--background-color-active: var(
--c--theme--colors--primary-300
);
--c--components--forms-checkbox--border-radius: 0;
--c--components--forms-datepicker--border-radius: 0;
--c--components--forms-fileuploader--border-radius: 0;
@@ -429,7 +445,18 @@
--c--components--forms-labelledbox--label-color--big: var(
--c--theme--colors--primary-text
);
--c--components--forms-select--border-radius: 0;
--c--components--forms-select--border-radius: 4px;
--c--components--forms-select--border-radius-hover: 4px;
--c--components--forms-select--background-color: #fff;
--c--components--forms-select--border-color: var(
--c--theme--colors--primary-text
);
--c--components--forms-select--border-color-hover: var(
--c--theme--colors--primary-text
);
--c--components--forms-select--box-shadow-color: var(
--c--theme--colors--primary-text
);
--c--components--forms-switch--handle-border-radius: 2px;
--c--components--forms-switch--rail-border-radius: 4px;
--c--components--forms-textarea--border-radius: 0;

View File

@@ -183,11 +183,14 @@ export const tokens = {
'forms-labelledbox': {
'label-color': {
small: 'var(--c--theme--colors--primary-500)',
'small-disabled': 'var(--c--theme--colors--greyscale-400)',
big: { disabled: 'var(--c--theme--colors--greyscale-400)' },
},
},
'forms-select': {
'border-color': 'var(--c--theme--colors--primary-500)',
'border-color-disabled-hover':
'var(--c--theme--colors--greyscale-200)',
'border-radius': {
hover: 'var(--c--components--forms-select--border-radius)',
focus: 'var(--c--components--forms-select--border-radius)',
@@ -345,10 +348,10 @@ export const tokens = {
'secondary-800': '#341f1f',
'secondary-900': '#2b1919',
'greyscale-text': '#303C4B',
'greyscale-000': '#cecece',
'greyscale-100': '#f6f6f6',
'greyscale-200': '#eeeeee',
'greyscale-300': '#e5e5e5',
'greyscale-000': '#f6f6f6',
'greyscale-100': '#eeeeee',
'greyscale-200': '#e5e5e5',
'greyscale-300': '#e1e1e1',
'greyscale-400': '#dddddd',
'greyscale-500': '#cecece',
'greyscale-600': '#7b7b7b',
@@ -421,6 +424,20 @@ export const tokens = {
color: 'var(--c--theme--colors--primary-text)',
},
},
datagrid: {
header: {
color: 'var(--c--theme--colors--primary-text)',
size: 'var(--c--theme--font--sizes--s)',
},
body: {
'background-color': 'transparent',
'background-color-hover': '#F4F4FD',
},
pagination: {
'background-color': 'transparent',
'background-color-active': 'var(--c--theme--colors--primary-300)',
},
},
'forms-checkbox': { 'border-radius': '0' },
'forms-datepicker': { 'border-radius': '0' },
'forms-fileuploader': { 'border-radius': '0' },
@@ -433,7 +450,14 @@ export const tokens = {
'forms-labelledbox': {
'label-color': { big: 'var(--c--theme--colors--primary-text)' },
},
'forms-select': { 'border-radius': '0' },
'forms-select': {
'border-radius': '4px',
'border-radius-hover': '4px',
'background-color': '#ffffff',
'border-color': 'var(--c--theme--colors--primary-text)',
'border-color-hover': 'var(--c--theme--colors--primary-text)',
'box-shadow-color': 'var(--c--theme--colors--primary-text)',
},
'forms-switch': {
'handle-border-radius': '2px',
'rail-border-radius': '4px',

View File

@@ -0,0 +1,89 @@
import { DataGrid, usePagination } from '@openfun/cunningham-react';
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import IconUser from '@/assets/icons/icon-user.svg';
import { Box, Card, TextErrors } from '@/components';
import { useCunninghamTheme } from '@/cunningham';
import { Team, useTeamAccesses } from '@/features/teams/api/';
import { PAGE_SIZE } from '@/features/teams/conf';
interface MemberGridProps {
team: Team;
}
export const MemberGrid = ({ team }: MemberGridProps) => {
const { t } = useTranslation();
const { colorsTokens } = useCunninghamTheme();
const pagination = usePagination({
pageSize: PAGE_SIZE,
});
const { page, pageSize, setPagesCount } = pagination;
const { data, isLoading, error } = useTeamAccesses({
teamId: team.id,
page,
});
const accesses = data?.results;
useEffect(() => {
setPagesCount(data?.count ? Math.ceil(data.count / pageSize) : 0);
}, [data?.count, pageSize, setPagesCount]);
return (
<Card
className="m-b pb-s"
$overflow="auto"
$css={`
margin-top:0;
& .c__pagination__goto {
display: none;
}
& table th:first-child,
& table td:first-child {
padding-right: 0;
width: 0;
}
`}
aria-label={t('List members card')}
>
{error && <TextErrors causes={error.cause} />}
<DataGrid
columns={[
{
id: 'icon-user',
renderCell() {
return (
<Box $direction="row" $align="center">
<IconUser
aria-label={t('Member icon')}
width={20}
height={20}
color={colorsTokens()['primary-600']}
/>
</Box>
);
},
},
{
headerName: t('Names'),
field: 'user.name',
},
{
field: 'user.email',
headerName: t('Emails'),
},
{
field: 'role',
headerName: t('Roles'),
},
]}
rows={accesses || []}
isLoading={isLoading}
pagination={pagination}
/>
</Card>
);
};

View File

@@ -1,2 +1,3 @@
export * from './Panel/Panel';
export * from './TeamInfo';
export * from './Member/MemberGrid';

View File

@@ -19,6 +19,15 @@
"{{label}} button": "Bouton {{label}}",
"{{label}} icon": "Icône {{label}}",
"Recents": "Récents",
"Admin": "Admin",
"Member": "Membre",
"Owner": "Propriétaire",
"Select a role": "Choisir un rôle",
"List members card": "Carte liste des membres",
"Member icon": "Icône de membre",
"Names": "Noms",
"Emails": "Emails",
"Roles": "Rôles",
"Sort the teams": "Trier les groupes",
"Sort teams icon": "Icône trier les groupes",
"Add a team": "Ajouter un groupe",

View File

@@ -5,7 +5,7 @@ import { ReactElement } from 'react';
import { Box } from '@/components';
import { TextErrors } from '@/components/TextErrors';
import { TeamInfo, useTeam } from '@/features/teams/';
import { MemberGrid, TeamInfo, useTeam } from '@/features/teams/';
import { NextPageWithLayout } from '@/types/next';
import TeamLayout from './TeamLayout';
@@ -47,7 +47,12 @@ const Team = ({ id }: TeamProps) => {
);
}
return <TeamInfo team={team} />;
return (
<>
<TeamInfo team={team} />
<MemberGrid team={team} />
</>
);
};
Page.getLayout = function getLayout(page: ReactElement) {