diff --git a/packages/app-builder/src/components/Cases/CasesList.tsx b/packages/app-builder/src/components/Cases/CasesList.tsx index 152d66a2..44bfb1b0 100644 --- a/packages/app-builder/src/components/Cases/CasesList.tsx +++ b/packages/app-builder/src/components/Cases/CasesList.tsx @@ -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'; @@ -18,13 +22,20 @@ const columnHelper = createColumnHelper(); 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([]); + + useEffect(() => { + onSortingChange(sorting); + }, [sorting, onSortingChange]); const columns = useMemo( () => [ @@ -32,6 +43,7 @@ export function CasesList({ id: 'status', header: t('cases:case.status'), size: 50, + enableSorting: false, cell: ({ getValue }) => ( ), @@ -41,6 +53,7 @@ export function CasesList({ header: t('cases:case.name'), size: 200, minSize: 120, + enableSorting: false, cell: ({ getValue }) => { const caseName = getValue(); return ( @@ -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 }) => (
tagId)} /> @@ -87,17 +102,23 @@ export function CasesList({ header: t('cases:case.contributors'), size: 80, minSize: 80, + enableSorting: false, cell: ({ 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 }) => ( { return { statuses: filters.statuses ?? [], @@ -58,6 +60,7 @@ export const buildQueryParams = ( } : {}, offsetId, + order, }; }; @@ -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)) { @@ -97,8 +104,11 @@ export async function loader({ request, params }: LoaderFunctionArgs) { export default function Cases() { const { t } = useTranslation(casesI18n); - const { casesData: initialCasesData, filters } = - useLoaderData(); + const { + casesData: initialCasesData, + filters, + pagination: initialPagination, + } = useLoaderData(); const inboxId = useParam('inboxId'); const { data, next, previous, reset } = useCursorPaginatedFetcher< @@ -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(); @@ -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, }), @@ -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], ); @@ -163,7 +198,22 @@ export default function Cases() {
- + { + const paginationParams: PaginationParams = { + ...omit(initialPagination, ['order']), + ...(state.length > 0 && { + order: state[0]?.desc ? 'DESC' : 'ASC', + }), + }; + + if (hasAlreadyOrdered) + navigateCasesList(filters, paginationParams); + hasAlreadyOrdered = true; + }} + />