From fd9c46685b6b34f90edfd2bcffafdc10cf32250f Mon Sep 17 00:00:00 2001 From: Melisa Anabella Rossi Date: Thu, 18 Jan 2024 13:16:38 -0300 Subject: [PATCH] feat: add table v2 (#495) --- package-lock.json | 84 ++++++---- src/components/v2/Table/Table.stories.tsx | 46 ++++++ .../Table/TableContainer/TableContainer.css | 80 ++++++++++ .../Table/TableContainer/TableContainer.tsx | 59 +++++++ .../TableContainer/TableContianer.types.tsx | 13 ++ .../v2/Table/TableContainer/index.tsx | 2 + .../v2/Table/TableContent/TableContent.css | 127 +++++++++++++++ .../Table/TableContent/TableContent.spec.tsx | 144 ++++++++++++++++++ .../v2/Table/TableContent/TableContent.tsx | 108 +++++++++++++ .../Table/TableContent/TableContent.types.tsx | 24 +++ .../v2/Table/TableContent/index.tsx | 2 + src/components/v2/index.ts | 4 + 12 files changed, 665 insertions(+), 28 deletions(-) create mode 100644 src/components/v2/Table/Table.stories.tsx create mode 100644 src/components/v2/Table/TableContainer/TableContainer.css create mode 100644 src/components/v2/Table/TableContainer/TableContainer.tsx create mode 100644 src/components/v2/Table/TableContainer/TableContianer.types.tsx create mode 100644 src/components/v2/Table/TableContainer/index.tsx create mode 100644 src/components/v2/Table/TableContent/TableContent.css create mode 100644 src/components/v2/Table/TableContent/TableContent.spec.tsx create mode 100644 src/components/v2/Table/TableContent/TableContent.tsx create mode 100644 src/components/v2/Table/TableContent/TableContent.types.tsx create mode 100644 src/components/v2/Table/TableContent/index.tsx create mode 100644 src/components/v2/index.ts diff --git a/package-lock.json b/package-lock.json index dc6cd3af..96c1e7b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49172,7 +49172,8 @@ "ajv-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", - "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==" + "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", + "requires": {} }, "ajv-keywords": { "version": "5.1.0", @@ -50757,7 +50758,8 @@ "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", - "dev": true + "dev": true, + "requires": {} }, "@mdx-js/util": { "version": "1.6.22", @@ -51788,7 +51790,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "ansi-styles": { "version": "4.3.0", @@ -52666,7 +52669,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "ansi-styles": { "version": "4.3.0", @@ -53444,7 +53448,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "ansi-styles": { "version": "4.3.0", @@ -54795,7 +54800,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "schema-utils": { "version": "1.0.0", @@ -55363,7 +55369,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -55798,7 +55805,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "json5": { "version": "1.0.2", @@ -55960,7 +55968,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "cosmiconfig": { "version": "6.0.0", @@ -56317,7 +56326,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -56347,7 +56357,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "schema-utils": { "version": "2.7.1", @@ -56455,7 +56466,8 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true + "dev": true, + "requires": {} }, "eslint-scope": { "version": "5.1.1", @@ -56504,7 +56516,8 @@ "version": "8.12.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz", "integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==", - "dev": true + "dev": true, + "requires": {} }, "yallist": { "version": "4.0.0", @@ -56784,7 +56797,8 @@ "version": "3.4.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", - "dev": true + "dev": true, + "requires": {} }, "ansi-styles": { "version": "4.3.0", @@ -58581,7 +58595,8 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "dev": true, + "requires": {} }, "acorn-walk": { "version": "7.2.0", @@ -58655,13 +58670,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true + "dev": true, + "requires": {} }, "ajv-keywords": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", - "dev": true + "dev": true, + "requires": {} }, "alphanum-sort": { "version": "1.0.2", @@ -59163,7 +59180,8 @@ "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true + "dev": true, + "requires": {} }, "babel-jest": { "version": "28.1.3", @@ -59414,7 +59432,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "emojis-list": { "version": "3.0.0", @@ -63703,7 +63722,8 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true + "dev": true, + "requires": {} }, "eslint-scope": { "version": "4.0.3", @@ -64445,7 +64465,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} } } } @@ -68739,7 +68760,8 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true + "dev": true, + "requires": {} }, "jest-regex-util": { "version": "26.0.0", @@ -70440,7 +70462,8 @@ "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -79298,7 +79321,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} } } } @@ -79358,7 +79382,8 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true + "dev": true, + "requires": {} }, "react-dom": { "version": "17.0.2", @@ -79534,7 +79559,8 @@ "react-virtualized-auto-sizer": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.11.tgz", - "integrity": "sha512-v2YlC4KCnjEF7V5KtxrHCy50vPhbL73BS1qNOXFYaaE1XGeRqZHrGP+F4BE0QDv2pP+f1t9twL1n5pRp5GPMkQ==" + "integrity": "sha512-v2YlC4KCnjEF7V5KtxrHCy50vPhbL73BS1qNOXFYaaE1XGeRqZHrGP+F4BE0QDv2pP+f1t9twL1n5pRp5GPMkQ==", + "requires": {} }, "read-cache": { "version": "1.0.0", @@ -83302,7 +83328,8 @@ "version": "3.4.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", - "dev": true + "dev": true, + "requires": {} }, "fast-deep-equal": { "version": "3.1.1", @@ -83528,7 +83555,8 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz", "integrity": "sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg==", - "dev": true + "dev": true, + "requires": {} }, "webpack-hot-middleware": { "version": "2.25.3", diff --git a/src/components/v2/Table/Table.stories.tsx b/src/components/v2/Table/Table.stories.tsx new file mode 100644 index 00000000..531a9d89 --- /dev/null +++ b/src/components/v2/Table/Table.stories.tsx @@ -0,0 +1,46 @@ +import React from 'react' +import TableContainer from './TableContainer' +import { TableContent } from './TableContent' +import { ComponentMeta, ComponentStory } from '@storybook/react' + +export default { + title: 'V2/Table', + component: TableContainer +} as ComponentMeta + +const Template: ComponentStory = (args) => ( + +) + +export const Basic = Template.bind({}) +Basic.args = { + children: ( + TEST 1 }, + { + column1: 'test2', + column2: ( +
+ TEST2 +
+ ) + } + ]} + activePage={1} + isLoading={false} + setPage={() => console.log('setPage')} + totalPages={2} + empty={() => null} + total={10} + hasHeaders + /> + ), + tabsList: [ + { displayValue: 'Tab1', value: 'tab1' }, + { displayValue: 'Tab2', value: 'tab2' } + ], + sortbyList: [], + handleSortByChange: (value: string) => console.log('sortBy', value), + sortBy: '' +} diff --git a/src/components/v2/Table/TableContainer/TableContainer.css b/src/components/v2/Table/TableContainer/TableContainer.css new file mode 100644 index 00000000..35fb2c08 --- /dev/null +++ b/src/components/v2/Table/TableContainer/TableContainer.css @@ -0,0 +1,80 @@ +.dui-table-container__filters { + display: flex; + border-top-right-radius: 10px; + border-top-left-radius: 10px; + align-items: center; + border-bottom: 1px solid var(--divider); + padding-left: 20px; + position: relative; +} + +.dui-table-container__filters .dcl.tab { + padding: 0px; + height: 46px; + align-items: center; + margin-top: 22px; +} + +.dui-table-container { + display: flex; + flex-direction: column; + border-radius: 12px; + margin-top: 48px; + background-color: var(--secondary); +} + +.dui-table-container__sort-by { + border-radius: 12px; + margin-right: 20px; + justify-content: space-between; + display: flex; + flex-direction: row; +} + +.dui-table-container__filters .ui.dropdown { + display: flex; + align-items: center; + font-size: 13px; + position: absolute; + right: 20px; +} + +.dui-table-container__filters .ui.dropdown > .icon { + height: 100%; + display: flex; + align-items: center; +} + +.dui-table-container__tabs { + font-size: 22px; + font-weight: 700; +} + +@media (max-width: 768px) { + .dui-table-container :global(.ui.button.basic) { + text-align: left; + } + + .dui-table-container__filters { + flex-direction: column; + padding: unset; + } + + .dui-table-container__tabs { + padding-left: unset; + } + + .dui-table-container__filters .ui.dropdown { + position: relative; + left: 0; + margin: 16px 12px 16px 0px; + align-self: flex-end; + } + .dui-table-container { + margin-top: 16px; + } + .dui-table-container .ui.very.basic.table tr th, + .dui-table-container .ui.very.basic.table tr td { + width: 50% !important; /* 2 columns, needs to be overridden with the !important since the library uses it too */ + } +} diff --git a/src/components/v2/Table/TableContainer/TableContainer.tsx b/src/components/v2/Table/TableContainer/TableContainer.tsx new file mode 100644 index 00000000..b2c5cdbb --- /dev/null +++ b/src/components/v2/Table/TableContainer/TableContainer.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import { forwardRef } from 'react' +import { Dropdown } from '../../../Dropdown/Dropdown' +import { Tabs } from '../../../Tabs/Tabs' +import { Props } from './TableContianer.types' +import './TableContainer.css' + +const TableContainer = forwardRef((props, ref) => { + const { + children, + tabsList, + activeTab, + handleTabChange, + sortbyList, + handleSortByChange, + sortBy + } = props + + return ( +
+ {tabsList.length || sortbyList?.length ? ( +
+ {tabsList.length > 0 ? ( + + {tabsList.map((tab) => ( + { + handleTabChange && handleTabChange(tab.value) + }} + > +
+ {tab.displayValue} +
+
+ ))} +
+ ) : null} + {sortbyList && ( + { + const value = data.value.toString() + handleSortByChange && handleSortByChange(value) + }} + options={sortbyList} + /> + )} +
+ ) : null} + {children} +
+ ) +}) + +export default TableContainer diff --git a/src/components/v2/Table/TableContainer/TableContianer.types.tsx b/src/components/v2/Table/TableContainer/TableContianer.types.tsx new file mode 100644 index 00000000..3a677365 --- /dev/null +++ b/src/components/v2/Table/TableContainer/TableContianer.types.tsx @@ -0,0 +1,13 @@ +import { DropdownItemProps } from 'semantic-ui-react/dist/commonjs/modules/Dropdown/DropdownItem' +import React, { RefObject } from 'react' + +export type Props = { + children: React.ReactNode + ref: RefObject + tabsList: { displayValue: string; value: string }[] + activeTab?: string + handleTabChange?: (tab: string) => void + sortbyList?: DropdownItemProps[] + handleSortByChange?: (value: string) => void + sortBy?: string +} diff --git a/src/components/v2/Table/TableContainer/index.tsx b/src/components/v2/Table/TableContainer/index.tsx new file mode 100644 index 00000000..911125c0 --- /dev/null +++ b/src/components/v2/Table/TableContainer/index.tsx @@ -0,0 +1,2 @@ +import TableContainer from './TableContainer' +export default TableContainer diff --git a/src/components/v2/Table/TableContent/TableContent.css b/src/components/v2/Table/TableContent/TableContent.css new file mode 100644 index 00000000..b93037cd --- /dev/null +++ b/src/components/v2/Table/TableContent/TableContent.css @@ -0,0 +1,127 @@ +.dui-table-content { + display: flex; + flex-direction: column; +} + +.dui-table-content .ui.table { + font-size: 14px; + line-height: 24px; + color: white; + font-weight: normal; + font-style: normal; + font-stretch: normal; +} + +.dui-table-content .header { + font-size: 16px; + font-weight: 700; +} + +.dui-table-content .ui.table th { + padding: 18px; + border: 1px solid var(--divider); +} + +.dui-table-content--radius-ending .ui.table tr:last-child td:first-child { + border-bottom-left-radius: 10px; +} + +.dui-table-content--radius-ending .ui.table tr:last-child td:last-child { + border-bottom-right-radius: 10px; +} + +.dui-table-content__headers--empty .ui.table th:first-child { + border-top-left-radius: 10px; +} + +.dui-table-content__headers--empty .ui.table th:last-child { + border-top-right-radius: 10px; +} + +.dui-table-content .ui.table td:first-child, +.dui-table-content .ui.table th:first-child { + padding: 18px !important; + border: 1px solid var(--divider); +} + +.dui-table-content .ui.table tr td { + border: 1px solid var(--divider); + padding: 15.5px; +} + +.dui-table-content .ui.table tr td { + border-top: 1px solid var(--divider); +} + +.dui-table-content .ui.table td a { + color: var(--text); +} + +.dui-table-content .ui.table td a.ui.button.inverted { + height: 32px; + font-size: 12px; + margin-left: 8px; +} + +.dui-table-content__table--empty { + width: 100%; + height: 404px; + display: flex; + align-items: center; + justify-content: center; + position: relative; +} + +.dui-table-content__pagination { + justify-content: flex-end; + gap: 20px; + display: flex; + color: var(--secondary-text); + align-items: center; + margin-bottom: 11px; +} + +.dui-table-content .ui.basic.table th { + font-size: 16px; + font-weight: 700; + color: white; +} + +@media (max-width: 768px) { + .dui-table-content .ui.basic.table tbody tr { + display: flex !important; + flex-direction: row; + align-items: center; + padding: 0; + } + .dui-table-content__pagination { + flex-direction: column; + } + .dui-table-content__pagination .ui.pagination.menu { + display: flex; + flex-direction: row; + } + .dui-table-content__pagination .ui.pagination.menu .item + .item { + margin: 0; + } + .dui-table-content__pagination .ui.pagination.menu { + width: 100%; + justify-content: center; + } + .dui-table-content__pagination { + grid-gap: 10px; + gap: 10px; + } + .dui-table-content .ui.menu:after { + display: none; + } + .dui-table-content .ui.very.basic.table tr { + border: 1px solid var(--divider); + } + .dui-table-content .ui.very.basic.table tr:first-of-type { + border: none; + } + .dui-table-content .ui.very.basic.table td { + border-right: 1px solid var(--divider) !important; + } +} diff --git a/src/components/v2/Table/TableContent/TableContent.spec.tsx b/src/components/v2/Table/TableContent/TableContent.spec.tsx new file mode 100644 index 00000000..72032210 --- /dev/null +++ b/src/components/v2/Table/TableContent/TableContent.spec.tsx @@ -0,0 +1,144 @@ +import React from 'react' +import { render, within } from '@testing-library/react' +import { DataTableType } from './TableContent.types' +import TableContent, { ROWS_PER_PAGE } from './TableContent' + +describe('Table content', () => { + let data: DataTableType[] = [ + { first_header: 'content header 1', second_header:
second text
}, + { + first_header: 'second content header 1', + second_header:
second text header 2
+ } + ] + + afterEach(() => { + jest.resetAllMocks() + }) + + describe('Empty table', () => { + it('should render the empty table message', async () => { + const { getByText } = render( +
empty table
} + total={0} + /> + ) + expect(getByText('empty table')).toBeInTheDocument() + }) + }) + + describe('Should render the table correctly', () => { + it('should render the table', async () => { + const screen = render( +
empty table
} + total={0} + /> + ) + + const { getByTestId } = screen + + expect(getByTestId('table-content')).not.toBe(null) + }) + + it('should render the headers', async () => { + const screen = render( +
empty table
} + total={0} + /> + ) + + const { getByText } = screen + + expect(getByText('first_header')).not.toBe(null) + expect(getByText('second_header')).not.toBe(null) + }) + + it('should render the content', async () => { + const screen = render( +
empty table
} + total={0} + /> + ) + + const { getByText } = screen + + expect(getByText('content header 1')).not.toBe(null) + expect(getByText('second text')).not.toBe(null) + expect(getByText('second content header 1')).not.toBe(null) + expect(getByText('second text header 2')).not.toBe(null) + }) + }) + + describe('Should render the loader if its loading', () => { + it('should render the loader', async () => { + const screen = render( +
empty table
} + total={0} + /> + ) + + expect(screen.getByTestId('loader')).toBeInTheDocument() + }) + }) + + describe('Pagination', () => { + describe('Should have pagination', () => { + it('should render the pagination correctly', async () => { + data = Array(ROWS_PER_PAGE).fill({ + first_header: 'contetnt 1', + second_header: 'content 2' + }) + + const screen = render( +
empty table
} + total={data.length} + totalPages={2} + /> + ) + + const { getByRole } = screen + + const navigation = getByRole('navigation') + + expect(within(navigation).getByText('1')).toBeInTheDocument() + expect(within(navigation).getByText('2')).toBeInTheDocument() + }) + }) + + describe('Should not have pagination', () => { + it('should not render pagination as there is no need', async () => { + const screen = render( +
empty table
} + total={data.length} + totalPages={1} + /> + ) + + const { queryByRole } = screen + + expect(queryByRole('navigation')).not.toBeInTheDocument() + }) + }) + }) +}) diff --git a/src/components/v2/Table/TableContent/TableContent.tsx b/src/components/v2/Table/TableContent/TableContent.tsx new file mode 100644 index 00000000..8c3dd9f0 --- /dev/null +++ b/src/components/v2/Table/TableContent/TableContent.tsx @@ -0,0 +1,108 @@ +import React from 'react' +import { useMobileMediaQuery } from '../../../Media' +import { Table } from '../../../Table/Table' +import { Loader } from '../../../Loader/Loader' +import { Pagination } from '../../../Pagination/Pagination' +import { Props } from './TableContent.types' +import './TableContent.css' + +const TABLE_SIBLINGS_RANGE_MOBILE = 0 +const TABLE_SIBLINGS_RANGE_DESKTOP = 1 +export const ROWS_PER_PAGE = 10 + +const TableContent = (props: Props) => { + const { + empty, + data, + isLoading, + totalPages, + activePage = 1, + setPage, + total, + rowsPerPage = ROWS_PER_PAGE, + hasHeaders = false, + i18n + } = props + + const isMobile = useMobileMediaQuery() + const headers = data.length > 0 ? Object.keys(data[0]) : null + const hasPagination = totalPages && totalPages > 1 + + return ( +
+ {isLoading ? ( +
+ +
+ ) : headers ? ( + + + + {headers.map((header) => ( + + {header} + + ))} + + {data?.map((data: unknown, index) => ( + + {headers.map((header: string) => ( + + {data[header]} + + ))} + + ))} + +
+ ) : ( + empty() + )} + {hasPagination && total && props.activePage !== undefined ? ( +
+ {`${i18n.sortBy.showing} ${ + (activePage - 1) * rowsPerPage + 1 + }-${Math.min(activePage * rowsPerPage, total)} ${ + i18n.sortBy.of + } ${total}`} + + setPage && setPage(+props.activePage) + } + firstItem={null} + lastItem={null} + /> +
+ ) : null} +
+ ) +} + +TableContent.defaultProps = { + i18n: { + sortBy: { + showing: 'Showing', + of: 'of' + } + } +} + +export default React.memo(TableContent) diff --git a/src/components/v2/Table/TableContent/TableContent.types.tsx b/src/components/v2/Table/TableContent/TableContent.types.tsx new file mode 100644 index 00000000..80b56dc6 --- /dev/null +++ b/src/components/v2/Table/TableContent/TableContent.types.tsx @@ -0,0 +1,24 @@ +import React from 'react' + +export type Props = { + activePage?: number + data: DataTableType[] + isLoading: boolean + setPage?: (page: number) => void + totalPages?: number | null + empty: () => void + total: number | null + rowsPerPage?: number + mobileTableBody?: React.ReactNode + hasHeaders?: boolean + i18n?: { + sortBy: { + showing: string + of: string + } + } +} + +export type DataTableType = { + [key: string]: React.ReactNode +} diff --git a/src/components/v2/Table/TableContent/index.tsx b/src/components/v2/Table/TableContent/index.tsx new file mode 100644 index 00000000..d7b7881c --- /dev/null +++ b/src/components/v2/Table/TableContent/index.tsx @@ -0,0 +1,2 @@ +import TableContent from './TableContent' +export { TableContent } diff --git a/src/components/v2/index.ts b/src/components/v2/index.ts new file mode 100644 index 00000000..f09ea8a5 --- /dev/null +++ b/src/components/v2/index.ts @@ -0,0 +1,4 @@ +import { TableContent } from './Table/TableContent' +import TableContainer from './Table/TableContainer' + +export { TableContent, TableContainer }