SmartTable.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import React from 'react';
  2. import Pagination from 'components/common/Pagination/Pagination';
  3. import { Table } from 'components/common/table/Table/Table.styled';
  4. import * as S from 'components/common/table/TableHeaderCell/TableHeaderCell.styled';
  5. import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell';
  6. import { TableState } from 'lib/hooks/useTableState';
  7. import {
  8. isColumnElement,
  9. SelectCell,
  10. TableHeaderCellProps,
  11. } from './TableColumn';
  12. import { TableRow } from './TableRow';
  13. interface SmartTableProps<T, TId extends IdType, OT = never> {
  14. tableState: TableState<T, TId, OT>;
  15. allSelectable?: boolean;
  16. selectable?: boolean;
  17. className?: string;
  18. placeholder?: string;
  19. isFullwidth?: boolean;
  20. paginated?: boolean;
  21. hoverable?: boolean;
  22. }
  23. export const SmartTable = <T, TId extends IdType, OT = never>({
  24. children,
  25. tableState,
  26. selectable = false,
  27. allSelectable = false,
  28. placeholder = 'No Data Found',
  29. isFullwidth = false,
  30. paginated = false,
  31. hoverable = false,
  32. }: React.PropsWithChildren<SmartTableProps<T, TId, OT>>) => {
  33. const handleRowSelection = React.useCallback(
  34. (row: T, checked: boolean) => {
  35. tableState.setRowsSelection([row], checked);
  36. },
  37. [tableState]
  38. );
  39. const headerRow = React.useMemo(() => {
  40. const headerCells = React.Children.map(children, (child) => {
  41. if (!isColumnElement<T, TId, OT>(child)) {
  42. return child;
  43. }
  44. const { headerCell, title, orderValue } = child.props;
  45. const HeaderCell = headerCell as
  46. | React.FC<TableHeaderCellProps<T, TId, OT>>
  47. | undefined;
  48. return HeaderCell ? (
  49. <S.TableHeaderCell>
  50. <HeaderCell
  51. orderValue={orderValue}
  52. orderable={tableState.orderable}
  53. tableState={tableState}
  54. />
  55. </S.TableHeaderCell>
  56. ) : (
  57. // TODO types will be changed after fixing TableHeaderCell
  58. <TableHeaderCell
  59. {...(tableState.orderable as never)}
  60. orderValue={orderValue as never}
  61. title={title}
  62. />
  63. );
  64. });
  65. return (
  66. <tr>
  67. {allSelectable ? (
  68. <SelectCell
  69. rowIndex={-1}
  70. el="th"
  71. selectable
  72. selected={tableState.selectedCount === tableState.data.length}
  73. onChange={tableState.toggleSelection}
  74. />
  75. ) : (
  76. <S.TableHeaderCell />
  77. )}
  78. {headerCells}
  79. </tr>
  80. );
  81. }, [children, allSelectable, tableState]);
  82. const bodyRows = React.useMemo(() => {
  83. if (tableState.data.length === 0) {
  84. const colspan = React.Children.count(children) + +selectable;
  85. return (
  86. <tr>
  87. <td colSpan={colspan}>{placeholder}</td>
  88. </tr>
  89. );
  90. }
  91. return tableState.data.map((dataItem, index) => {
  92. return (
  93. <TableRow
  94. key={tableState.idSelector(dataItem)}
  95. index={index}
  96. hoverable={hoverable}
  97. dataItem={dataItem}
  98. tableState={tableState}
  99. selectable={selectable}
  100. onSelectChange={handleRowSelection}
  101. >
  102. {children}
  103. </TableRow>
  104. );
  105. });
  106. }, [
  107. children,
  108. handleRowSelection,
  109. hoverable,
  110. placeholder,
  111. selectable,
  112. tableState,
  113. ]);
  114. return (
  115. <>
  116. <Table isFullwidth={isFullwidth}>
  117. <thead>{headerRow}</thead>
  118. <tbody>{bodyRows}</tbody>
  119. </Table>
  120. {paginated && tableState.totalPages !== undefined && (
  121. <Pagination totalPages={tableState.totalPages} />
  122. )}
  123. </>
  124. );
  125. };