Refactored teams components.

This commit is contained in:
Mike Cao 2024-02-05 20:29:00 -08:00
parent 0e144269ee
commit be5592446a
25 changed files with 122 additions and 81 deletions

View file

@ -0,0 +1,46 @@
'use client';
import { useApi, useMessages } from 'components/hooks';
import { Icon, Icons, LoadingButton, Text } from 'react-basics';
import { touch } from 'store/modified';
export function TeamMemberRemoveButton({
teamId,
userId,
disabled,
onSave,
}: {
teamId: string;
userId: string;
disabled?: boolean;
onSave?: () => void;
}) {
const { formatMessage, labels } = useMessages();
const { del, useMutation } = useApi();
const { mutate, isPending } = useMutation({
mutationFn: () => del(`/teams/${teamId}/users/${userId}`),
});
const handleRemoveTeamMember = () => {
mutate(null, {
onSuccess: () => {
touch('team:members');
onSave?.();
},
});
};
return (
<LoadingButton
onClick={() => handleRemoveTeamMember()}
disabled={disabled}
isLoading={isPending}
>
<Icon>
<Icons.Close />
</Icon>
<Text>{formatMessage(labels.remove)}</Text>
</LoadingButton>
);
}
export default TeamMemberRemoveButton;

View file

@ -0,0 +1,17 @@
'use client';
import TeamMembersDataTable from './TeamMembersDataTable';
import PageHeader from 'components/layout/PageHeader';
import { useMessages } from 'components/hooks';
export function TeamMembers({ teamId }: { teamId: string }) {
const { formatMessage, labels } = useMessages();
return (
<>
<PageHeader title={formatMessage(labels.members)} />
<TeamMembersDataTable teamId={teamId} allowEdit={true} />
</>
);
}
export default TeamMembers;

View file

@ -0,0 +1,22 @@
'use client';
import DataTable from 'components/common/DataTable';
import TeamMembersTable from './TeamMembersTable';
import { useTeamMembers } from 'components/hooks';
export function TeamMembersDataTable({
teamId,
allowEdit = false,
}: {
teamId: string;
allowEdit?: boolean;
}) {
const queryResult = useTeamMembers(teamId);
return (
<DataTable queryResult={queryResult}>
{({ data }) => <TeamMembersTable data={data} teamId={teamId} allowEdit={allowEdit} />}
</DataTable>
);
}
export default TeamMembersDataTable;

View file

@ -0,0 +1,48 @@
'use client';
import { GridColumn, GridTable, useBreakpoint } from 'react-basics';
import { useMessages, useLogin } from 'components/hooks';
import { ROLES } from 'lib/constants';
import TeamMemberRemoveButton from './TeamMemberRemoveButton';
export function TeamMembersTable({
data = [],
teamId,
allowEdit,
}: {
data: any[];
teamId: string;
allowEdit: boolean;
}) {
const { formatMessage, labels } = useMessages();
const { user } = useLogin();
const breakpoint = useBreakpoint();
const roles = {
[ROLES.teamOwner]: formatMessage(labels.teamOwner),
[ROLES.teamMember]: formatMessage(labels.teamMember),
};
return (
<GridTable data={data} cardMode={['xs', 'sm', 'md'].includes(breakpoint)}>
<GridColumn name="username" label={formatMessage(labels.username)}>
{row => row?.user?.username}
</GridColumn>
<GridColumn name="role" label={formatMessage(labels.role)}>
{row => roles[row?.role]}
</GridColumn>
<GridColumn name="action" label=" " alignment="end">
{row => {
return (
allowEdit &&
row?.role !== ROLES.teamOwner &&
user?.id !== row?.id && (
<TeamMemberRemoveButton teamId={teamId} userId={row?.user?.id} />
)
);
}}
</GridColumn>
</GridTable>
);
}
export default TeamMembersTable;

View file

@ -0,0 +1,15 @@
import TeamMembers from './TeamMembers';
import TeamProvider from 'app/(main)/teams/[teamId]/TeamProvider';
import { Metadata } from 'next';
export default function ({ params: { teamId } }) {
return (
<TeamProvider teamId={teamId}>
<TeamMembers teamId={teamId} />
</TeamProvider>
);
}
export const metadata: Metadata = {
title: 'Team members - Umami',
};