2
0

Table.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import React from "react";
  2. import styled from "styled-components";
  3. import { Column, Row, useGlobalFilter, useTable } from "react-table";
  4. import Loading from "components/Loading";
  5. const GlobalFilter: React.FunctionComponent<any> = ({ setGlobalFilter }) => {
  6. const [value, setValue] = React.useState("");
  7. const onChange = (value: string) => {
  8. setValue(value);
  9. setGlobalFilter(value || undefined);
  10. };
  11. return (
  12. <SearchRow>
  13. <i className="material-icons">search</i>
  14. <SearchInput
  15. value={value}
  16. onChange={(e: any) => {
  17. onChange(e.target.value);
  18. }}
  19. placeholder="Search"
  20. />
  21. </SearchRow>
  22. );
  23. };
  24. export type TableProps = {
  25. columns: Column<any>[];
  26. data: any[];
  27. onRowClick?: (row: Row) => void;
  28. isLoading: boolean;
  29. disableGlobalFilter?: boolean;
  30. disableHover?: boolean;
  31. };
  32. const Table: React.FC<TableProps> = ({
  33. columns: columnsData,
  34. data,
  35. onRowClick,
  36. isLoading,
  37. disableGlobalFilter = false,
  38. disableHover,
  39. }) => {
  40. const {
  41. getTableProps,
  42. getTableBodyProps,
  43. rows,
  44. setGlobalFilter,
  45. prepareRow,
  46. headerGroups,
  47. visibleColumns,
  48. } = useTable(
  49. {
  50. columns: columnsData,
  51. data,
  52. },
  53. useGlobalFilter
  54. );
  55. const renderRows = () => {
  56. if (isLoading) {
  57. return (
  58. <StyledTr disableHover={true} selected={false}>
  59. <StyledTd colSpan={visibleColumns.length}>
  60. <Loading />
  61. </StyledTd>
  62. </StyledTr>
  63. );
  64. }
  65. if (!rows.length) {
  66. return (
  67. <StyledTr disableHover={true} selected={false}>
  68. <StyledTd colSpan={visibleColumns.length}>No data available</StyledTd>
  69. </StyledTr>
  70. );
  71. }
  72. return (
  73. <>
  74. {rows.map((row) => {
  75. prepareRow(row);
  76. return (
  77. <StyledTr
  78. disableHover={disableHover}
  79. {...row.getRowProps()}
  80. enablePointer={!!onRowClick}
  81. onClick={() => onRowClick && onRowClick(row)}
  82. selected={false}
  83. >
  84. {row.cells.map((cell) => (
  85. <StyledTd {...cell.getCellProps()}>
  86. {cell.render("Cell")}
  87. </StyledTd>
  88. ))}
  89. </StyledTr>
  90. );
  91. })}
  92. </>
  93. );
  94. };
  95. return (
  96. <TableWrapper>
  97. {!disableGlobalFilter && (
  98. <GlobalFilter setGlobalFilter={setGlobalFilter} />
  99. )}
  100. <StyledTable {...getTableProps()}>
  101. <StyledTHead>
  102. {headerGroups.map((headerGroup) => (
  103. <StyledTr
  104. {...headerGroup.getHeaderGroupProps()}
  105. disableHover={true}
  106. >
  107. {headerGroup.headers.map((column) => (
  108. <StyledTh {...column.getHeaderProps()}>
  109. {column.render("Header")}
  110. </StyledTh>
  111. ))}
  112. </StyledTr>
  113. ))}
  114. </StyledTHead>
  115. <tbody {...getTableBodyProps()}>{renderRows()}</tbody>
  116. </StyledTable>
  117. </TableWrapper>
  118. );
  119. };
  120. export default Table;
  121. const TableWrapper = styled.div`
  122. padding-bottom: 20px;
  123. `;
  124. type StyledTrProps = {
  125. enablePointer?: boolean;
  126. disableHover?: boolean;
  127. selected?: boolean;
  128. };
  129. export const StyledTr = styled.tr`
  130. line-height: 2.2em;
  131. background: ${(props: StyledTrProps) => (props.selected ? "#ffffff11" : "")};
  132. :hover {
  133. background: ${(props: StyledTrProps) =>
  134. props.disableHover ? "" : "#ffffff22"};
  135. }
  136. cursor: ${(props: StyledTrProps) =>
  137. props.enablePointer ? "pointer" : "unset"};
  138. `;
  139. export const StyledTd = styled.td`
  140. font-size: 13px;
  141. color: #ffffff;
  142. :first-child {
  143. padding-left: 10px;
  144. }
  145. :last-child {
  146. padding-right: 10px;
  147. }
  148. user-select: text;
  149. `;
  150. export const StyledTHead = styled.thead`
  151. width: 100%;
  152. border-top: 1px solid #aaaabb22;
  153. border-bottom: 1px solid #aaaabb22;
  154. `;
  155. export const StyledTh = styled.th`
  156. text-align: left;
  157. font-size: 13px;
  158. font-weight: 500;
  159. color: #aaaabb;
  160. :first-child {
  161. padding-left: 10px;
  162. }
  163. :last-child {
  164. padding-right: 10px;
  165. }
  166. `;
  167. export const StyledTable = styled.table`
  168. width: 100%;
  169. min-width: 500px;
  170. border-collapse: collapse;
  171. `;
  172. const SearchInput = styled.input`
  173. outline: none;
  174. border: none;
  175. font-size: 13px;
  176. background: none;
  177. width: 100%;
  178. color: white;
  179. padding: 0;
  180. height: 20px;
  181. `;
  182. const SearchRow = styled.div`
  183. display: flex;
  184. width: 100%;
  185. font-size: 13px;
  186. color: #ffffff55;
  187. border-radius: 4px;
  188. user-select: none;
  189. align-items: center;
  190. padding: 10px 0px;
  191. min-width: 300px;
  192. max-width: min-content;
  193. background: #ffffff11;
  194. margin-bottom: 15px;
  195. margin-top: 0px;
  196. i {
  197. width: 18px;
  198. height: 18px;
  199. margin-left: 12px;
  200. margin-right: 12px;
  201. font-size: 20px;
  202. }
  203. `;