fix: bug fixes (#397)

* Add more html page titles

* Make tables responsive

* fix react query keys

* Add tooltip to sidebar toggle

* fix: trim inputs

* fix inputs
This commit is contained in:
Philip Okugbe
2024-10-13 17:09:45 +01:00
committed by GitHub
parent fa3c8a03e1
commit 36e720920b
38 changed files with 681 additions and 612 deletions

View File

@@ -7,7 +7,7 @@ import { useNavigate } from "react-router-dom";
import { MultiUserSelect } from "@/features/group/components/multi-user-select.tsx";
const formSchema = z.object({
name: z.string().min(2).max(50),
name: z.string().trim().min(2).max(50),
description: z.string().max(500),
});

View File

@@ -1,69 +1,72 @@
import { Table, Group, Text, Anchor } from "@mantine/core";
import { useGetGroupsQuery } from "@/features/group/queries/group-query";
import {Table, Group, Text, Anchor} from "@mantine/core";
import {useGetGroupsQuery} from "@/features/group/queries/group-query";
import React from "react";
import { Link } from "react-router-dom";
import { IconGroupCircle } from "@/components/icons/icon-people-circle.tsx";
import {Link} from "react-router-dom";
import {IconGroupCircle} from "@/components/icons/icon-people-circle.tsx";
export default function GroupList() {
const { data, isLoading } = useGetGroupsQuery();
const {data, isLoading} = useGetGroupsQuery();
return (
<>
{data && (
<Table highlightOnHover verticalSpacing="sm">
<Table.Thead>
<Table.Tr>
<Table.Th>Group</Table.Th>
<Table.Th>Members</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>
{data?.items.map((group, index) => (
<Table.Tr key={index}>
<Table.Td>
<Anchor
size="sm"
underline="never"
style={{
cursor: "pointer",
color: "var(--mantine-color-text)",
}}
component={Link}
to={`/settings/groups/${group.id}`}
>
<Group gap="sm">
<IconGroupCircle />
<div>
<Text fz="sm" fw={500}>
{group.name}
</Text>
<Text fz="xs" c="dimmed">
{group.description}
</Text>
</div>
</Group>
</Anchor>
</Table.Td>
<Table.Td>
<Anchor
size="sm"
underline="never"
style={{
cursor: "pointer",
color: "var(--mantine-color-text)",
}}
component={Link}
to={`/settings/groups/${group.id}`}
>
{group.memberCount} members
</Anchor>
</Table.Td>
<Table.ScrollContainer minWidth={400}>
<Table highlightOnHover verticalSpacing="sm">
<Table.Thead>
<Table.Tr>
<Table.Th>Group</Table.Th>
<Table.Th>Members</Table.Th>
</Table.Tr>
))}
</Table.Tbody>
</Table>
</Table.Thead>
<Table.Tbody>
{data?.items.map((group, index) => (
<Table.Tr key={index}>
<Table.Td>
<Anchor
size="sm"
underline="never"
style={{
cursor: "pointer",
color: "var(--mantine-color-text)",
}}
component={Link}
to={`/settings/groups/${group.id}`}
>
<Group gap="sm" wrap="nowrap">
<IconGroupCircle/>
<div>
<Text fz="sm" fw={500} lineClamp={1}>
{group.name}
</Text>
<Text fz="xs" c="dimmed" lineClamp={2}>
{group.description}
</Text>
</div>
</Group>
</Anchor>
</Table.Td>
<Table.Td>
<Anchor
size="sm"
underline="never"
style={{
cursor: "pointer",
color: "var(--mantine-color-text)",
whiteSpace: "nowrap"
}}
component={Link}
to={`/settings/groups/${group.id}`}
>
{group.memberCount} members
</Anchor>
</Table.Td>
</Table.Tr>
))}
</Table.Tbody>
</Table>
</Table.ScrollContainer>
)}
</>
);

View File

@@ -1,20 +1,20 @@
import { Group, Table, Text, Badge, Menu, ActionIcon } from "@mantine/core";
import {Group, Table, Text, Badge, Menu, ActionIcon} from "@mantine/core";
import {
useGroupMembersQuery,
useRemoveGroupMemberMutation,
} from "@/features/group/queries/group-query";
import { useParams } from "react-router-dom";
import {useParams} from "react-router-dom";
import React from "react";
import { IconDots } from "@tabler/icons-react";
import { modals } from "@mantine/modals";
import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import {IconDots} from "@tabler/icons-react";
import {modals} from "@mantine/modals";
import {CustomAvatar} from "@/components/ui/custom-avatar.tsx";
import useUserRole from "@/hooks/use-user-role.tsx";
export default function GroupMembersList() {
const { groupId } = useParams();
const { data, isLoading } = useGroupMembersQuery(groupId);
const {groupId} = useParams();
const {data, isLoading} = useGroupMembersQuery(groupId);
const removeGroupMember = useRemoveGroupMemberMutation();
const { isAdmin } = useUserRole();
const {isAdmin} = useUserRole();
const onRemove = async (userId: string) => {
const memberToRemove = {
@@ -34,72 +34,74 @@ export default function GroupMembersList() {
</Text>
),
centered: true,
labels: { confirm: "Delete", cancel: "Cancel" },
confirmProps: { color: "red" },
labels: {confirm: "Delete", cancel: "Cancel"},
confirmProps: {color: "red"},
onConfirm: () => onRemove(userId),
});
return (
<>
{data && (
<Table verticalSpacing="sm">
<Table.Thead>
<Table.Tr>
<Table.Th>User</Table.Th>
<Table.Th>Status</Table.Th>
<Table.Th></Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>
{data?.items.map((user, index) => (
<Table.Tr key={index}>
<Table.Td>
<Group gap="sm">
<CustomAvatar avatarUrl={user.avatarUrl} name={user.name} />
<div>
<Text fz="sm" fw={500}>
{user.name}
</Text>
<Text fz="xs" c="dimmed">
{user.email}
</Text>
</div>
</Group>
</Table.Td>
<Table.Td>
<Badge variant="light">Active</Badge>
</Table.Td>
<Table.Td>
{isAdmin && (
<Menu
shadow="xl"
position="bottom-end"
offset={20}
width={200}
withArrow
arrowPosition="center"
>
<Menu.Target>
<ActionIcon variant="subtle" c="gray">
<IconDots size={20} stroke={2} />
</ActionIcon>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item onClick={() => openRemoveModal(user.id)}>
Remove group member
</Menu.Item>
</Menu.Dropdown>
</Menu>
)}
</Table.Td>
<Table.ScrollContainer minWidth={500}>
<Table verticalSpacing="sm">
<Table.Thead>
<Table.Tr>
<Table.Th>User</Table.Th>
<Table.Th>Status</Table.Th>
<Table.Th></Table.Th>
</Table.Tr>
))}
</Table.Tbody>
</Table>
</Table.Thead>
<Table.Tbody>
{data?.items.map((user, index) => (
<Table.Tr key={index}>
<Table.Td>
<Group gap="sm">
<CustomAvatar avatarUrl={user.avatarUrl} name={user.name}/>
<div>
<Text fz="sm" fw={500}>
{user.name}
</Text>
<Text fz="xs" c="dimmed">
{user.email}
</Text>
</div>
</Group>
</Table.Td>
<Table.Td>
<Badge variant="light">Active</Badge>
</Table.Td>
<Table.Td>
{isAdmin && (
<Menu
shadow="xl"
position="bottom-end"
offset={20}
width={200}
withArrow
arrowPosition="center"
>
<Menu.Target>
<ActionIcon variant="subtle" c="gray">
<IconDots size={20} stroke={2}/>
</ActionIcon>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item onClick={() => openRemoveModal(user.id)}>
Remove group member
</Menu.Item>
</Menu.Dropdown>
</Menu>
)}
</Table.Td>
</Table.Tr>
))}
</Table.Tbody>
</Table>
</Table.ScrollContainer>
)}
</>
);

View File

@@ -29,24 +29,22 @@ export function useGetGroupsQuery(
export function useGroupQuery(groupId: string): UseQueryResult<IGroup, Error> {
return useQuery({
queryKey: ['groups', groupId],
queryKey: ['group', groupId],
queryFn: () => getGroupById(groupId),
enabled: !!groupId,
});
}
export function useGroupMembersQuery(groupId: string) {
return useQuery({
queryKey: ['groupMembers', groupId],
queryFn: () => getGroupMembers(groupId),
enabled: !!groupId,
});
}
export function useCreateGroupMutation() {
const queryClient = useQueryClient();
return useMutation<IGroup, Error, Partial<IGroup>>({
mutationFn: (data) => createGroup(data),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['groups'],
});
notifications.show({ message: 'Group created successfully' });
},
onError: () => {
@@ -96,6 +94,14 @@ export function useDeleteGroupMutation() {
});
}
export function useGroupMembersQuery(groupId: string) {
return useQuery({
queryKey: ['groupMembers', groupId],
queryFn: () => getGroupMembers(groupId),
enabled: !!groupId,
});
}
export function useAddGroupMemberMutation() {
const queryClient = useQueryClient();