Skip to content

Commit

Permalink
feat(useTable): add use table for offline managing (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosthe19916 authored Nov 18, 2021
1 parent e233cb3 commit bc57577
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 10 deletions.
9 changes: 9 additions & 0 deletions src/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface Page {
page: number;
perPage: number;
}

export interface SortBy {
index: number;
direction: 'asc' | 'desc';
}
1 change: 1 addition & 0 deletions src/hooks/useTable/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useTable } from './useTable';
144 changes: 144 additions & 0 deletions src/hooks/useTable/useTable.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { renderHook } from '@testing-library/react-hooks';
import { Page } from '../../common/types';
import { useTable } from './useTable';

describe('useTableFilter', () => {
it('Pagination', () => {
const items = [...Array(15)].map((_, index) => index + 1);
const page: Page = { page: 1, perPage: 10 };

const { result } = renderHook(() =>
useTable<number>({
items: items,
currentPage: page,
filterItem: () => true,
compareToByColumn: () => 1,
})
);

// Page1
expect(result.current.pageItems).toEqual(items.slice(0, 10));
});

it('Filter', () => {
const items = [...Array(15)].map((_, index) => index + 1);
const page: Page = { page: 1, perPage: 10 };

const { result } = renderHook(() =>
useTable<number>({
items: items,
currentPage: page,
filterItem: (value) => value % 2 === 1,
compareToByColumn: () => 1,
})
);

// Page1
const expectedResult = [1, 3, 5, 7, 9, 11, 13, 15];
expect(result.current.pageItems).toEqual(expectedResult);
});

it('SortBy', () => {
const items = [...Array(15)].map((_, index) => index + 1);
const page: Page = { page: 1, perPage: 10 };
const filterItem = () => true;
const compareToByColumn = (a: number, b: number, indexCol?: number) =>
indexCol === 7 ? a - b : 0;

// Verify asc
const { result: resultAsc } = renderHook(() =>
useTable<number>({
items: items,
currentPage: page,
filterItem: filterItem,
currentSortBy: { direction: 'asc', index: 7 },
compareToByColumn: compareToByColumn,
})
);

const expectedAscResult = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
expect(resultAsc.current.pageItems).toEqual(expectedAscResult);

// Verify desc
const { result: resultDesc } = renderHook(() =>
useTable<number>({
items: items,
currentPage: page,
filterItem: filterItem,
currentSortBy: { direction: 'desc', index: 7 },
compareToByColumn: compareToByColumn,
})
);

const expectedDescResult = [15, 14, 13, 12, 11, 10, 9, 8, 7, 6];
expect(resultDesc.current.pageItems).toEqual(expectedDescResult);
});

it("SortBy when 'compareToByColumn' return always 0", () => {
const items = [...Array(15)].map((_, index) => index + 1);
const page: Page = { page: 1, perPage: 10 };

const expectedResult = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Verify asc
const { result: resultAsc } = renderHook(() =>
useTable<number>({
items: items,
currentPage: page,
filterItem: () => true,
currentSortBy: { direction: 'asc', index: 7 },
compareToByColumn: () => 0, // forcing comparison true
})
);

expect(resultAsc.current.pageItems).toEqual(expectedResult);

// Verify desc
const { result: resultDesc } = renderHook(() =>
useTable<number>({
items: items,
currentPage: page,
filterItem: () => true,
currentSortBy: { direction: 'desc', index: 7 },
compareToByColumn: () => 0, // forcing comparison true
})
);

expect(resultDesc.current.pageItems).toEqual(expectedResult);
});

it("SortBy when 'compareToByColumn' return always 0 and 'filter' is applied", () => {
const items = [...Array(25)].map((_, index) => index + 1);
const page: Page = { page: 1, perPage: 10 };
const filterItem = (val: number) => val % 2 === 0;
const compareToByColumn = () => 0; // forcing comparison true

const expectedResult = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20];

// Verify asc
const { result: resultAsc } = renderHook(() =>
useTable<number>({
items: items,
currentPage: page,
filterItem: filterItem,
currentSortBy: { direction: 'asc', index: 7 },
compareToByColumn: compareToByColumn,
})
);

expect(resultAsc.current.pageItems).toEqual(expectedResult);

// Verify desc
const { result: resultDesc } = renderHook(() =>
useTable<number>({
items: items,
currentPage: page,
filterItem: filterItem,
currentSortBy: { direction: 'desc', index: 7 },
compareToByColumn: compareToByColumn,
})
);

expect(resultDesc.current.pageItems).toEqual(expectedResult);
});
});
64 changes: 64 additions & 0 deletions src/hooks/useTable/useTable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useMemo } from 'react';
import { SortByDirection } from '@patternfly/react-table';
import { Page, SortBy } from '../../common/types';

// Hook

interface HookArgs<T> {
items?: T[];

currentSortBy?: SortBy;
compareToByColumn: (a: T, b: T, columnIndex?: number) => number;

currentPage: Page;
filterItem: (value: T) => boolean;
}

interface HookState<T> {
pageItems: T[];
filteredItems: T[];
}

export const useTable = <T>({
items,
currentSortBy,
currentPage,
filterItem,
compareToByColumn,
}: HookArgs<T>): HookState<T> => {
const state: HookState<T> = useMemo(() => {
const allItems = [...(items || [])];

// Filter
const filteredItems = allItems.filter(filterItem);

// Sort
let orderChanged = false;

let sortedItems: T[];
sortedItems = [...filteredItems].sort((a, b) => {
const comparisonResult = compareToByColumn(a, b, currentSortBy?.index);
if (comparisonResult !== 0) {
orderChanged = true;
}
return comparisonResult;
});

if (orderChanged && currentSortBy?.direction === SortByDirection.desc) {
sortedItems = sortedItems.reverse();
}

// Paginate
const pageItems = sortedItems.slice(
(currentPage.page - 1) * currentPage.perPage,
currentPage.page * currentPage.perPage
);

return {
pageItems,
filteredItems,
};
}, [items, currentPage, currentSortBy, compareToByColumn, filterItem]);

return state;
};
11 changes: 1 addition & 10 deletions src/hooks/useTableControls/useTableControls.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import { useCallback, useReducer } from 'react';
import { ActionType, createAction, getType } from 'typesafe-actions';
import { IExtraColumnData, SortByDirection } from '@patternfly/react-table';

export interface Page {
page: number;
perPage: number;
}

export interface SortBy {
index: number;
direction: 'asc' | 'desc';
}
import { Page, SortBy } from '../../common/types';

// Actions

Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export * from './components/StatusIcon';

export * from './hooks/useDelete';
export * from './hooks/useModal';
export * from './hooks/useTable';
export * from './hooks/useTableControls';
export * from './hooks/useToolbar';

0 comments on commit bc57577

Please sign in to comment.