Skip to content

Commit

Permalink
feat: adding ordering by created_at on the case manager
Browse files Browse the repository at this point in the history
  • Loading branch information
carere committed Jan 16, 2025
1 parent 2d22a96 commit 0439e50
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 10 deletions.
27 changes: 24 additions & 3 deletions packages/app-builder/src/components/Cases/CasesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import { formatDateTime, useFormatLanguage } from '@app-builder/utils/format';
import { getRoute } from '@app-builder/utils/routes';
import { fromUUID } from '@app-builder/utils/short-uuid';
import { Link } from '@remix-run/react';
import { createColumnHelper, getCoreRowModel } from '@tanstack/react-table';
import {
createColumnHelper,
getCoreRowModel,
type SortingState,
} from '@tanstack/react-table';
import clsx from 'clsx';
import { useMemo } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Table, Tooltip, useVirtualTable } from 'ui-design-system';

Expand All @@ -18,20 +22,28 @@ const columnHelper = createColumnHelper<Case>();

export function CasesList({
className,
onSortingChange,
cases,
}: {
cases: Case[];
onSortingChange: (state: SortingState) => void;
className?: string;
}) {
const { t } = useTranslation(casesI18n);
const language = useFormatLanguage();
const [sorting, setSorting] = useState<SortingState>([]);

useEffect(() => {
onSortingChange(sorting);
}, [sorting, onSortingChange]);

const columns = useMemo(
() => [
columnHelper.accessor(({ status }) => status, {
id: 'status',
header: t('cases:case.status'),
size: 50,
enableSorting: false,
cell: ({ getValue }) => (
<CaseStatus size="big" type="first-letter" status={getValue()} />
),
Expand All @@ -41,6 +53,7 @@ export function CasesList({
header: t('cases:case.name'),
size: 200,
minSize: 120,
enableSorting: false,
cell: ({ getValue }) => {
const caseName = getValue();
return (
Expand Down Expand Up @@ -71,11 +84,13 @@ export function CasesList({
header: t('cases:case.decisions'),
size: 60,
minSize: 60,
enableSorting: false,
}),
columnHelper.accessor(({ tags }) => tags, {
id: 'tags',
header: t('cases:case.tags'),
size: 100,
enableSorting: false,
cell: ({ getValue }) => (
<div className="p-2">
<CaseTags caseTagIds={getValue().map(({ tagId }) => tagId)} />
Expand All @@ -87,17 +102,23 @@ export function CasesList({
header: t('cases:case.contributors'),
size: 80,
minSize: 80,
enableSorting: false,
cell: ({ getValue }) => <CaseContributors contributors={getValue()} />,
}),
],
[language, t],
);

const { table, getBodyProps, rows, getContainerProps } = useVirtualTable({
data: cases,
columns,
columnResizeMode: 'onChange',
getCoreRowModel: getCoreRowModel(),
enableSorting: false,
state: {
sorting,
},
manualSorting: true,
onSortingChange: setSorting,
rowLink: ({ id }) => (
<Link
to={getRoute('/cases/:caseId', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { type Namespace } from 'i18next';
import qs from 'qs';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { omit } from 'remeda';
import { Button } from 'ui-design-system';
import { Icon } from 'ui-icons';

Expand All @@ -42,6 +43,7 @@ export const handle = {
export const buildQueryParams = (
filters: CasesFilters,
offsetId: string | null,
order: 'ASC' | 'DESC' | null,
) => {
return {
statuses: filters.statuses ?? [],
Expand All @@ -58,6 +60,7 @@ export const buildQueryParams = (
}
: {},
offsetId,
order,
};
};

Expand All @@ -75,16 +78,20 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
return redirect(getRoute('/cases/inboxes/:inboxId', { inboxId }));
}

const filters = parsedQuery.data;
const filtersForBackend: CaseFilters = {
...parsedQuery.data,
...parsedPaginationQuery.data,
inboxIds: [inboxId],
};

try {
const caseList = await cases.listCases(filtersForBackend);

return json({ casesData: caseList, filters });
return json({
casesData: caseList,
filters: parsedQuery.data,
pagination: parsedPaginationQuery.data,
});
} catch (error) {
// if inbox is deleted or user no longer have access, the user is redirected
if (isNotFoundHttpError(error) || isForbiddenHttpError(error)) {
Expand All @@ -97,8 +104,11 @@ export async function loader({ request, params }: LoaderFunctionArgs) {

export default function Cases() {
const { t } = useTranslation(casesI18n);
const { casesData: initialCasesData, filters } =
useLoaderData<typeof loader>();
const {
casesData: initialCasesData,
filters,
pagination: initialPagination,
} = useLoaderData<typeof loader>();
const inboxId = useParam('inboxId');

const { data, next, previous, reset } = useCursorPaginatedFetcher<
Expand All @@ -107,9 +117,13 @@ export default function Cases() {
>({
transform: (fetcherData) => fetcherData.casesData,
initialData: initialCasesData,
getQueryParams: (cursor) => buildQueryParams(filters, cursor),
getQueryParams: (cursor) =>
buildQueryParams(filters, cursor, initialPagination.order ?? null),
validateData: (data) => data.items.length > 0,
});

let hasAlreadyOrdered = false;

const { items: cases, ...pagination } = data;

const navigate = useNavigate();
Expand All @@ -122,7 +136,7 @@ export default function Cases() {
pathname: getRoute('/cases/inboxes/:inboxId', {
inboxId: fromUUID(inboxId),
}),
search: qs.stringify(buildQueryParams(casesFilters, null), {
search: qs.stringify(buildQueryParams(casesFilters, null, null), {
addQueryPrefix: true,
skipNulls: true,
}),
Expand All @@ -138,6 +152,27 @@ export default function Cases() {
if (pagination.previous) {
previous();
}
if (!pagination.order) {
console.log('resetting');
reset();
}
if (pagination.order) {
navigate(
{
pathname: getRoute('/cases/inboxes/:inboxId', {
inboxId: fromUUID(inboxId),
}),
search: qs.stringify(
buildQueryParams(casesFilters, null, pagination.order),
{
addQueryPrefix: true,
skipNulls: true,
},
),
},
{ replace: true },
);
}
},
[navigate, inboxId, next, previous, reset],
);
Expand All @@ -163,7 +198,22 @@ export default function Cases() {
</CaseRightPanel.Trigger>
</div>
<CasesFiltersBar />
<CasesList cases={cases} className="max-h-[60dvh]" />
<CasesList
cases={cases}
className="max-h-[60dvh]"
onSortingChange={(state) => {
const paginationParams: PaginationParams = {
...omit(initialPagination, ['order']),
...(state.length > 0 && {
order: state[0]?.desc ? 'DESC' : 'ASC',
}),
};

if (hasAlreadyOrdered)
navigateCasesList(filters, paginationParams);
hasAlreadyOrdered = true;
}}
/>
<CursorPaginationButtons
items={cases}
onPaginationChange={(paginationParams: PaginationParams) =>
Expand Down

0 comments on commit 0439e50

Please sign in to comment.