From df35d87759ced4f21d5bd09cb3bb4809e6c276c3 Mon Sep 17 00:00:00 2001 From: Vitali Karpuk Date: Mon, 12 Feb 2024 20:52:47 +0300 Subject: [PATCH] add table --- ui/components/atoms/loader/constants.ts | 11 ++ ui/components/atoms/loader/index.ts | 2 + ui/components/atoms/loader/loader.gif | Bin 0 -> 61139 bytes ui/components/atoms/loader/loader.tsx | 87 ++++++++++++ .../tableErrorMessage/TableErrorMessage.tsx | 16 +++ .../img/tablePlaceholder.svg | 25 ++++ .../atoms/tableErrorMessage/index.module.css | 52 ++++++++ .../atoms/tableErrorMessage/index.ts | 1 + .../selectPlate/SelectPlate.module.css | 81 ++++++++++++ .../molecules/selectPlate/img/Arrow.svg | 3 + ui/components/molecules/selectPlate/index.tsx | 28 ++++ .../singleSelect/SingleSelect.module.css | 19 +++ .../molecules/singleSelect/index.tsx | 1 + .../molecules/singleSelect/singleSelect.tsx | 81 ++++++++++++ .../accountConent/accountContent.tsx | 70 +++++++++- .../organisms/accountConent/constants.ts | 31 +++++ .../organisms/accountConent/img/iconMock.svg | 70 ++++++++++ .../organisms/accountConent/index.module.css | 3 +- .../organisms/navigation/navigation.tsx | 8 +- .../organisms/pager/Pager.module.css | 37 ++++++ .../organisms/pager/img/ArrowIcon.svg | 3 + ui/components/organisms/pager/index.tsx | 124 ++++++++++++++++++ .../organisms/pagination/index.module.css | 76 +++++++++++ ui/components/organisms/pagination/index.ts | 1 + .../organisms/pagination/pagination.tsx | 55 ++++++++ .../organisms/table/errorMessage.tsx | 20 +++ .../organisms/table/img/ChevronIcon.svg | 3 + .../organisms/table/img/SortIcon.svg | 3 + ui/components/organisms/table/img/clear.svg | 3 + .../organisms/table/index.module.css | 59 +++++++++ ui/components/organisms/table/index.ts | 1 + ui/components/organisms/table/table.tsx | 109 +++++++++++++++ .../accountTemplate/accountTemplate.tsx | 39 ++++++ .../templates/amountTemplate/index.module.css | 7 + .../table/templates/amountTemplate/index.tsx | 29 ++++ .../buttonTemplate/buttonTemplate.tsx | 18 +++ .../templates/cardsTemplate/cardsTemplate.tsx | 42 ++++++ .../table/templates/index.module.css | 50 +++++++ .../organisms/table/templates/index.tsx | 37 ++++++ .../templates/namesTemplate/namesTemplate.tsx | 28 ++++ .../table/templates/stringTemplate/index.tsx | 55 ++++++++ .../templates/timeTemplate/timeTemplate.tsx | 41 ++++++ ui/helpers/timeHelper.ts | 96 ++++++++++++++ ui/hooks/useHandleClickOutside.ts | 24 ++++ ui/hooks/useTable.ts | 81 ++++++++++++ ui/package-lock.json | 22 ++++ ui/package.json | 2 + ui/pages/account/index.tsx | 2 + 48 files changed, 1652 insertions(+), 4 deletions(-) create mode 100644 ui/components/atoms/loader/constants.ts create mode 100644 ui/components/atoms/loader/index.ts create mode 100644 ui/components/atoms/loader/loader.gif create mode 100644 ui/components/atoms/loader/loader.tsx create mode 100644 ui/components/atoms/tableErrorMessage/TableErrorMessage.tsx create mode 100644 ui/components/atoms/tableErrorMessage/img/tablePlaceholder.svg create mode 100644 ui/components/atoms/tableErrorMessage/index.module.css create mode 100644 ui/components/atoms/tableErrorMessage/index.ts create mode 100644 ui/components/molecules/selectPlate/SelectPlate.module.css create mode 100644 ui/components/molecules/selectPlate/img/Arrow.svg create mode 100644 ui/components/molecules/selectPlate/index.tsx create mode 100644 ui/components/molecules/singleSelect/SingleSelect.module.css create mode 100644 ui/components/molecules/singleSelect/index.tsx create mode 100644 ui/components/molecules/singleSelect/singleSelect.tsx create mode 100644 ui/components/organisms/accountConent/constants.ts create mode 100644 ui/components/organisms/accountConent/img/iconMock.svg create mode 100644 ui/components/organisms/pager/Pager.module.css create mode 100644 ui/components/organisms/pager/img/ArrowIcon.svg create mode 100644 ui/components/organisms/pager/index.tsx create mode 100644 ui/components/organisms/pagination/index.module.css create mode 100644 ui/components/organisms/pagination/index.ts create mode 100644 ui/components/organisms/pagination/pagination.tsx create mode 100644 ui/components/organisms/table/errorMessage.tsx create mode 100644 ui/components/organisms/table/img/ChevronIcon.svg create mode 100644 ui/components/organisms/table/img/SortIcon.svg create mode 100644 ui/components/organisms/table/img/clear.svg create mode 100644 ui/components/organisms/table/index.module.css create mode 100644 ui/components/organisms/table/index.ts create mode 100644 ui/components/organisms/table/table.tsx create mode 100644 ui/components/organisms/table/templates/accountTemplate/accountTemplate.tsx create mode 100644 ui/components/organisms/table/templates/amountTemplate/index.module.css create mode 100644 ui/components/organisms/table/templates/amountTemplate/index.tsx create mode 100644 ui/components/organisms/table/templates/buttonTemplate/buttonTemplate.tsx create mode 100644 ui/components/organisms/table/templates/cardsTemplate/cardsTemplate.tsx create mode 100644 ui/components/organisms/table/templates/index.module.css create mode 100644 ui/components/organisms/table/templates/index.tsx create mode 100644 ui/components/organisms/table/templates/namesTemplate/namesTemplate.tsx create mode 100644 ui/components/organisms/table/templates/stringTemplate/index.tsx create mode 100644 ui/components/organisms/table/templates/timeTemplate/timeTemplate.tsx create mode 100644 ui/helpers/timeHelper.ts create mode 100644 ui/hooks/useHandleClickOutside.ts create mode 100644 ui/hooks/useTable.ts diff --git a/ui/components/atoms/loader/constants.ts b/ui/components/atoms/loader/constants.ts new file mode 100644 index 0000000..525bc93 --- /dev/null +++ b/ui/components/atoms/loader/constants.ts @@ -0,0 +1,11 @@ +export const colorConfig = { + blue: [ + 'rgba(222, 229, 255, 1)', + 'rgba(189, 204, 255, 1)', + 'rgba(155, 178, 255, 1)', + 'rgba(122, 153, 255, 1)', + 'rgba(89, 127, 255, 1)', + ], +}; + +export const disabledColor = 'rgba(232, 233, 235, 1)'; diff --git a/ui/components/atoms/loader/index.ts b/ui/components/atoms/loader/index.ts new file mode 100644 index 0000000..9a5222d --- /dev/null +++ b/ui/components/atoms/loader/index.ts @@ -0,0 +1,2 @@ +export { default as Loader } from './loader'; +export { LoaderVariant } from './loader'; diff --git a/ui/components/atoms/loader/loader.gif b/ui/components/atoms/loader/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ae031d5dde9f2f9901ca2e7a7a6ca0db77320d1 GIT binary patch literal 61139 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 Qv>x(wG*lPC zI>{pLJT5s6wOgr+e!<+z&`H{Q#c1dh{FtPmvFZeBbzaXaQ_ z`o?mYu)pr+yyDAKy<_8@>6?O0_Il%G$70!;K^A+xiRxp<)RU}mg_>hwB(*MC>)B2g zKKwMbE7;Q6lwt2Y-)TPTXx^FT<=zW3mGy%Ecq-8J42yj37w&L#o%Ah>Z1k1Yi>t#f zKn6ji$8JCyTeObOI02|$k(Z{#;5`;hSzyK31aXL-$J463b04ju$eT-%g}=q3Ro0a6 zSU?KmE_x#o7}4uW8%>;&MrCbX*!)nCz|wt}s=tFv!y@}}4rJ=)QYna%+Gr-ls!?Kz zFD8Trk-)+EQD6jMGnZ$&3Hl|bMMJv+)}c*W_~E5zDRRe!67bc*m|cMw8p@5C@aTP+ z;u=95l!2>|9TG}LQ|S8oeJBdA5v6Ai(3v2~AaS{z6Eki!554A@#G5mA0+?ZpzeR_*A%0A_WvxZ-MWbz!}U+BFAT5d&3=6Q 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 y91u6YuzsG$|Dt9zd#A+rH4FUn>z^m^&lC9P3H { + const r = radius; + const g = gap; + const colors = colorConfig.blue; + + const getCX = (r, g, i) => r + (r * 2 + g) * i; + const width = getCX(r, g, dotCount - 1) + r; + + const getCircles = (count) => { + const arr = []; + + for (let i = 0; i < count; i++) { + let values = []; + for (let index = 0; index < count * 2 - 1; index++) { + values.push(index < i || index > count + i - 1 ? 0 : 1); + } + values = [0, ...values, 0]; + arr.push( + + {!disabled && ( + + )} + + ); + } + return arr; + }; + + if (variant === LoaderVariant.CIRCLE) { + return ...loading; + } + + return ( + + {getCircles(dotCount)} + + ); +}; + +export default Loader; diff --git a/ui/components/atoms/tableErrorMessage/TableErrorMessage.tsx b/ui/components/atoms/tableErrorMessage/TableErrorMessage.tsx new file mode 100644 index 0000000..72b262e --- /dev/null +++ b/ui/components/atoms/tableErrorMessage/TableErrorMessage.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import noDataIcon from './img/tablePlaceholder.svg'; + +import styles from './index.module.css'; +import classNames from 'classnames'; +import Image from 'next/image'; + +const TableErrorMessage = () => { + return ( +
+ +

There is no data yet

+
+ ); +}; +export default TableErrorMessage; diff --git a/ui/components/atoms/tableErrorMessage/img/tablePlaceholder.svg b/ui/components/atoms/tableErrorMessage/img/tablePlaceholder.svg new file mode 100644 index 0000000..81d8136 --- /dev/null +++ b/ui/components/atoms/tableErrorMessage/img/tablePlaceholder.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/components/atoms/tableErrorMessage/index.module.css b/ui/components/atoms/tableErrorMessage/index.module.css new file mode 100644 index 0000000..087409c --- /dev/null +++ b/ui/components/atoms/tableErrorMessage/index.module.css @@ -0,0 +1,52 @@ +.errorTitle { + margin: 16px 0 0px; + font-size: 16px; +} + +.errorTitleWithBtn { + margin: 16px 0 8px; +} + +.descriptionError { + margin-bottom: 20px; + color: rgba(0, 0, 0, 0.4); + font-size: 14px; +} + +.errorScreen { + padding: 48px 0 32px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; +} + +.button { + margin-bottom: 16px; + font-size: 14px; + color: #597fff; + background-color: #eef1ff; + border: 1px solid #597fff; + border-radius: 7px; + padding: 10px 12px; + display: flex; + align-items: center; +} + +.button:last-child { + margin: 0; +} + +.button:hover { + background: #e8ecfa; + cursor: pointer; +} + +.button:active { + background: #d7dffa; +} + +.button svg { + margin-right: 4px; + fill: #597fff; +} diff --git a/ui/components/atoms/tableErrorMessage/index.ts b/ui/components/atoms/tableErrorMessage/index.ts new file mode 100644 index 0000000..1cbd085 --- /dev/null +++ b/ui/components/atoms/tableErrorMessage/index.ts @@ -0,0 +1 @@ +export { default as TableErrorMessage } from './TableErrorMessage'; diff --git a/ui/components/molecules/selectPlate/SelectPlate.module.css b/ui/components/molecules/selectPlate/SelectPlate.module.css new file mode 100644 index 0000000..f0708fa --- /dev/null +++ b/ui/components/molecules/selectPlate/SelectPlate.module.css @@ -0,0 +1,81 @@ +.selectPlate { + width: max-content; + display: flex; + align-items: center; + justify-content: space-between; + cursor: pointer; + padding: 4px 12px; + user-select: none; + background-color: #f0f1f5; + border: 2px solid transparent; + border-radius: 7px; + transition: all ease 200ms; + } + + .selectPlate * { + transition: all ease 200ms; + } + + .selectPlate > * { + margin-right: 6px; + } + + .selectPlate > *:last-child { + margin-right: 0; + } + + .selectTitle { + font-weight: 600; + color: rgba(0, 0, 0, 0.8); + line-height: 24px; + text-transform: capitalize; + white-space: nowrap; + } + + .selectCount { + font-weight: 500; + color: rgba(0, 0, 0, 0.8); + line-height: 16px; + text-align: center; + padding: 2px 8px; + border-radius: 30px; + background-color: #fff; + } + + .selectClear { + display: flex; + align-items: center; + transition: all ease 200ms; + } + + .selectClear:hover { + transform: scale(1.2); + } + + .arrow { + fill: rgba(0, 0, 0, 0.8); + transform: rotateX(180deg); + } + + .arrowDisabled { + fill: rgba(0, 0, 0, 0.4); + } + + .expanded { + border: 2px solid #ebebf0; + } + + .active { + border: 2px solid #e3e8fd; + background-color: #eef1ff; + } + + .active span { + color: #3e66ec; + } + + .active svg { + fill: #3e66ec; + } + + \ No newline at end of file diff --git a/ui/components/molecules/selectPlate/img/Arrow.svg b/ui/components/molecules/selectPlate/img/Arrow.svg new file mode 100644 index 0000000..4f0226c --- /dev/null +++ b/ui/components/molecules/selectPlate/img/Arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/components/molecules/selectPlate/index.tsx b/ui/components/molecules/selectPlate/index.tsx new file mode 100644 index 0000000..0edc676 --- /dev/null +++ b/ui/components/molecules/selectPlate/index.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import style from './SelectPlate.module.css'; +import ArrowIcon from './img/Arrow.svg'; +import classNames from 'classnames'; +import Image from 'next/image'; + +type SelectPlateProps = { + onClick: () => void; + expanded: boolean; + title: string; + disable: boolean; +}; + +const SelectPlate = ({ onClick, expanded, title, disable }: SelectPlateProps): JSX.Element => { + return ( +
+ {title} + +
+ ); +}; + +export default SelectPlate; diff --git a/ui/components/molecules/singleSelect/SingleSelect.module.css b/ui/components/molecules/singleSelect/SingleSelect.module.css new file mode 100644 index 0000000..fb7427f --- /dev/null +++ b/ui/components/molecules/singleSelect/SingleSelect.module.css @@ -0,0 +1,19 @@ +.singleSelect { + position: relative; +} + +.dropdown { + padding: 0; + border-radius: 7px; + width: 100%; +} + +.item { + padding: 6px 12px; + transition: all ease 200ms; + cursor: pointer; +} + +.item:hover { + background-color: var(--col--gray3); +} diff --git a/ui/components/molecules/singleSelect/index.tsx b/ui/components/molecules/singleSelect/index.tsx new file mode 100644 index 0000000..e4acc98 --- /dev/null +++ b/ui/components/molecules/singleSelect/index.tsx @@ -0,0 +1 @@ +export { default as SingleSelect } from './singleSelect'; diff --git a/ui/components/molecules/singleSelect/singleSelect.tsx b/ui/components/molecules/singleSelect/singleSelect.tsx new file mode 100644 index 0000000..d915629 --- /dev/null +++ b/ui/components/molecules/singleSelect/singleSelect.tsx @@ -0,0 +1,81 @@ +import React, { useEffect, useRef, useState } from 'react'; +import style from './SingleSelect.module.css'; +import DropdownWrapper from '../dropdownWrapper/index'; +import classNames from 'classnames'; +import SelectPlate from '../selectPlate'; +import CustomScrollList from '../customScrollList'; +import { LimitOptions } from '../../../comman/types'; +import { useMedia } from '../../../hooks/useMedia'; +import { useHandleClickOutside } from '../../../hooks/useHandleClickOutside'; + +type SingleSelectProps = { + options: LimitOptions; + selectTitle?: string; + onChange: (value: any) => void; + initValue?: number; + disable?: boolean; + className?: string; +}; + +const SingleSelect = ({ + options, + selectTitle = '', + onChange, + initValue, + disable, + className, +}: SingleSelectProps): JSX.Element => { + const [selected, setSelected] = useState(initValue); + const [expanded, setExpanded] = useState(false); + const ref = useRef(); + const media = useMedia(0); + + const findTextByValue = (val) => { + if (!options || (!val && val !== 0)) return null; + const res = options?.filter((elem) => Object.values(elem).indexOf(val) > -1); + if (res.length > 0) return res[0].text; + return null; + }; + + useEffect(() => { + setSelected(initValue); + }, [initValue]); + + const clickHandler = (data) => { + if (!disable) { + setSelected(data); + onChange(data); + setExpanded(false); + } + }; + + useHandleClickOutside(ref.current, () => (media.greater.sm ? setExpanded(false) : null)); + + return ( +
+ setExpanded(!expanded)} + expanded={expanded} + title={findTextByValue(selected) || selectTitle} + disable={disable} + /> + setExpanded(false)} show={expanded}> + + {options?.map((el) => ( +
{ + clickHandler(el.value); + }} + > + {el.text} +
+ ))} +
+
+
+ ); +}; + +export default SingleSelect; diff --git a/ui/components/organisms/accountConent/accountContent.tsx b/ui/components/organisms/accountConent/accountContent.tsx index c530f27..fb3e98f 100644 --- a/ui/components/organisms/accountConent/accountContent.tsx +++ b/ui/components/organisms/accountConent/accountContent.tsx @@ -1,14 +1,82 @@ +import { ORDER_BY, SORT_BY } from "../../../comman/types"; +import { useTable } from "../../../hooks/useTable"; import { ConnectWalletButton } from "../../molecules/connectWalletButton"; +import { Table } from "../table"; +import { ScoringConfig } from "./constants"; +import iconMock from "./img/iconMock.svg"; import style from "./index.module.css"; const AccountContent = () => { + const mockData = { + data: [ + { id: "Evgeniy-dev.mina", url: iconMock, time: 1707757181674 }, + { id: "mina.mina", url: iconMock, time: 1707757181674 }, + { id: "Evgeniy-dev.mina", url: iconMock, time: 1707757181674 }, + { id: "mina.mina", url: iconMock, time: 1707757181674 }, + { id: "Evgeniy-dev.mina", url: iconMock, time: 1707757181674 }, + { id: "Vitality.mina", url: iconMock, time: 1707757181674 }, + { id: "@@@@@@@.mina", url: iconMock, time: 1707757181674 }, + ], + size: 100, + totalPages: 1, + pageable: { + sort: { + sorted: true, + unsorted: false, + empty: false, + }, + offset: 0, + pageNumber: 0, + pageSize: 100, + paged: true, + unpaged: false, + }, + last: false, + totalElements: 2, + number: 0, + sort: { + sorted: true, + unsorted: false, + empty: false, + }, + first: true, + numberOfElements: 100, + empty: false, + }; return (
My Names
-
+ { + console.log(data); + }} + onChangeLimit={(data) => { + console.log(data); + }} + onChangeSort={(data) => { + console.log(data); + }} + onChangeOrder={(data) => { + console.log(data); + }} + /> ); }; diff --git a/ui/components/organisms/accountConent/constants.ts b/ui/components/organisms/accountConent/constants.ts new file mode 100644 index 0000000..7c27127 --- /dev/null +++ b/ui/components/organisms/accountConent/constants.ts @@ -0,0 +1,31 @@ +import { SORT_BY } from "../../../comman/types"; +import { TableTemplates } from "../table/templates"; + +export const ScoringConfig = [ + { + colName: "names", + headerText: "Registered Names", + columnTemplate: TableTemplates.NAMES, + fields: { + value: "id", + url: "url", + }, + }, + { + colName: "button", + columnTemplate: TableTemplates.BUTTON, + headerText: "", + fields: { + value: "Manage", + }, + }, + { + colName: "Created", + columnTemplate: TableTemplates.TIME, + headerText: "Created", + fields: { + value: "time", + }, + sortBy: SORT_BY.SCORE, + }, +]; diff --git a/ui/components/organisms/accountConent/img/iconMock.svg b/ui/components/organisms/accountConent/img/iconMock.svg new file mode 100644 index 0000000..1dc8b95 --- /dev/null +++ b/ui/components/organisms/accountConent/img/iconMock.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/components/organisms/accountConent/index.module.css b/ui/components/organisms/accountConent/index.module.css index d6f8e1d..cdd07c3 100644 --- a/ui/components/organisms/accountConent/index.module.css +++ b/ui/components/organisms/accountConent/index.module.css @@ -2,12 +2,13 @@ display: flex; flex-direction: column; width: 100%; + padding: 0 40px; } .header { display: flex; justify-content: space-between; - padding: 16px 0 16px 16px; + padding: 16px 0 16px 0px; } .header > div:first-child { diff --git a/ui/components/organisms/navigation/navigation.tsx b/ui/components/organisms/navigation/navigation.tsx index 710c912..1a0a04b 100644 --- a/ui/components/organisms/navigation/navigation.tsx +++ b/ui/components/organisms/navigation/navigation.tsx @@ -23,8 +23,12 @@ const Navigation = () => { [style.active]: pathname.includes(url), })} > - + {title} ); diff --git a/ui/components/organisms/pager/Pager.module.css b/ui/components/organisms/pager/Pager.module.css new file mode 100644 index 0000000..6891a1b --- /dev/null +++ b/ui/components/organisms/pager/Pager.module.css @@ -0,0 +1,37 @@ +.pager { + display: flex; +} +.btn { + outline: none !important; + border: none; + background-color: transparent; + min-width: 32px; + height: 32px; + padding: 0 4px; + margin-right: 4px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 7px; + transition: all ease 200ms; + line-height: 16px; + user-select: none; + color: rgba(0, 0, 0, 0.8); + cursor: pointer; +} + +.btn:hover { + background-color: #f0f1f5; +} +.btn:last-child { + margin-right: 0; +} +.ellipsis { + cursor: default; +} +.ellipsis:hover { + background-color: transparent; +} +.active { + background-color: #f0f1f5; +} diff --git a/ui/components/organisms/pager/img/ArrowIcon.svg b/ui/components/organisms/pager/img/ArrowIcon.svg new file mode 100644 index 0000000..60324ba --- /dev/null +++ b/ui/components/organisms/pager/img/ArrowIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/components/organisms/pager/index.tsx b/ui/components/organisms/pager/index.tsx new file mode 100644 index 0000000..04e1177 --- /dev/null +++ b/ui/components/organisms/pager/index.tsx @@ -0,0 +1,124 @@ +import classNames from 'classnames'; +import React from 'react'; +import style from './Pager.module.css'; +import ArrowIcon from './img/ArrowIcon.svg'; +import Image from 'next/image'; +import { useMedia } from '../../../hooks/useMedia'; + +type PagerProps = { + page: number; + count?: number; + onChange: (value: number) => void; + pageNeighbours?: number; +}; + +const Pager = ({ page, count = 1, onChange, pageNeighbours = 1 }: PagerProps): JSX.Element => { + const showPrevButton = page !== 1; + const showNextButton = count !== page; + const media = useMedia(); + + const ELLIPSIS = '...'; + + const range = (from, to, step = 1) => { + let i = from; + const range = []; + + while (i <= to) { + range.push(i); + i += step; + } + + return range; + }; + + const fetchPageNumbers = () => { + const totalNumbers = pageNeighbours * 2 + 3; + const totalBlocks = totalNumbers + 2; + + if (count > totalBlocks) { + const startPage = Math.max(2, page - pageNeighbours); + const endPage = Math.min(count - 1, page + pageNeighbours); + let pages = range(startPage, endPage); + const hasLeftSpill = startPage > 2; + const hasRightSpill = count - endPage > 1; + const spillOffset = totalNumbers - (pages.length + 1); + switch (true) { + case hasLeftSpill && !hasRightSpill: { + const extraPages = + (page + 1 + '').length > 3 && !media.greater.sm + ? range(startPage - spillOffset + 2, startPage - 1) + : range(startPage - spillOffset, startPage - 1); + pages = [ELLIPSIS, ...extraPages, ...pages]; + break; + } + case !hasLeftSpill && hasRightSpill: { + const extraPages = range(endPage + 1, endPage + spillOffset); + pages = [...pages, ...extraPages, ELLIPSIS]; + break; + } + + case hasLeftSpill && hasRightSpill: + default: { + (page + 1 + '').length > 3 && !media.greater.sm + ? (pages = [ELLIPSIS, pages[1], ELLIPSIS]) + : (pages = [ELLIPSIS, ...pages, ELLIPSIS]); + break; + } + } + + return [1, ...pages, count]; + } + + return range(1, count); + }; + + const changeHandler = (value) => { + if (value > count || value < 1) return; + onChange(value - 1); + }; + + return ( +
+ {showPrevButton && ( + + )} + + {fetchPageNumbers().map((el, i) => { + if (el === ELLIPSIS) + return ( + + ); + + return ( + + ); + })} + + {showNextButton && ( + + )} +
+ ); +}; + +export default Pager; diff --git a/ui/components/organisms/pagination/index.module.css b/ui/components/organisms/pagination/index.module.css new file mode 100644 index 0000000..a5c497c --- /dev/null +++ b/ui/components/organisms/pagination/index.module.css @@ -0,0 +1,76 @@ +.pagination { + background-color: #fff; + position: sticky; + top: 0; + z-index: 12; + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 0 16px 0; + user-select: none; +} + +.showing { + line-height: 32px; + flex-basis: 25%; + font-size: 14px; + color: rgba(0, 0, 0, 0.8); +} + +.showingMobile { + flex-basis: auto; +} + +.select { + flex-basis: 25%; + display: flex; + align-items: center; + justify-content: flex-end; +} + +.select span { + margin-right: 8px; + font-size: 14px; + color: rgba(0, 0, 0, 0.8); +} + +.totalCount { + margin-bottom: 4px; + line-height: 18px; +} + +.showingLast { + color: #9c9ea6; + font-size: 12px; +} + +@media (max-width: 992px) { + .showingHiddenOnMobile { + display: none; + } +} + +@media (max-width: 768px) { + .pagination { + justify-content: center; + } + .MobileWithShowing { + flex-direction: column-reverse; + align-items: flex-start; + gap: 10px; + padding-right: 16px; + } + + .select span { + display: none; + } +} + +@media (max-width: 576px) { + .pagination { + padding: 12px 0; + justify-content: flex-start; + padding-left: 16px; + } +} diff --git a/ui/components/organisms/pagination/index.ts b/ui/components/organisms/pagination/index.ts new file mode 100644 index 0000000..8bdff8c --- /dev/null +++ b/ui/components/organisms/pagination/index.ts @@ -0,0 +1 @@ +export { default as Table } from './pagination'; diff --git a/ui/components/organisms/pagination/pagination.tsx b/ui/components/organisms/pagination/pagination.tsx new file mode 100644 index 0000000..743c738 --- /dev/null +++ b/ui/components/organisms/pagination/pagination.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import style from './index.module.css'; +import { LimitOptions } from '../../../comman/types'; +import Pager from '../pager'; +import { SingleSelect } from '../../molecules/singleSelect'; + +type PaginationProps = { + currentPage: number; + pagesCount: number; + pageLimit: number; + totalElements: number; + onChangePage: (value: number | string) => void; + onChangeLimit: (value: number) => void; + isLoading: boolean; + limitOptions?: LimitOptions; +}; + +const Pagination = ({ + currentPage, + pageLimit, + totalElements, + pagesCount, + onChangePage, + limitOptions, + onChangeLimit, + isLoading, +}: PaginationProps): JSX.Element => { + const nextOffset = pageLimit * (currentPage + 1); + const offset = pageLimit * currentPage; + + return ( +
+
+

+ Showing {offset + 1} - {nextOffset > totalElements ? totalElements : nextOffset} out of{' '} + {totalElements ?? '...'} +

+
+
+ onChangePage(page)} /> +
+
+ Show + +
+
+ ); +}; + +export default Pagination; diff --git a/ui/components/organisms/table/errorMessage.tsx b/ui/components/organisms/table/errorMessage.tsx new file mode 100644 index 0000000..58bfce5 --- /dev/null +++ b/ui/components/organisms/table/errorMessage.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import ClearIcon from './img/clear.svg'; + +import styles from './Table.module.css'; +import Image from 'next/image'; + +const ErrorMessage = ({ errorText, onClearStr }) => { + return ( +
+

{errorText ?? 'There is no data yet'}

+ {onClearStr && ( + + )} +
+ ); +}; +export default ErrorMessage; diff --git a/ui/components/organisms/table/img/ChevronIcon.svg b/ui/components/organisms/table/img/ChevronIcon.svg new file mode 100644 index 0000000..97e4524 --- /dev/null +++ b/ui/components/organisms/table/img/ChevronIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/components/organisms/table/img/SortIcon.svg b/ui/components/organisms/table/img/SortIcon.svg new file mode 100644 index 0000000..5491805 --- /dev/null +++ b/ui/components/organisms/table/img/SortIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/components/organisms/table/img/clear.svg b/ui/components/organisms/table/img/clear.svg new file mode 100644 index 0000000..65723bc --- /dev/null +++ b/ui/components/organisms/table/img/clear.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/components/organisms/table/index.module.css b/ui/components/organisms/table/index.module.css new file mode 100644 index 0000000..2dbd884 --- /dev/null +++ b/ui/components/organisms/table/index.module.css @@ -0,0 +1,59 @@ +.wrapper { + overflow: hidden; + overflow-x: scroll; +} + +.wrapper::-webkit-scrollbar { + display: none; +} + +.table { + overflow: hidden; + overflow-x: scroll; + width: 100%; + border-collapse: collapse; +} + +.table tbody tr:hover { + background-color: rgb(250, 250, 252); + transition: all 0.3s; + min-width: 100px; +} + +.table thead { + font-weight: bold; + border-top: 0.5px solid var(--col--gray8); + padding: 10px 0; +} + +.table thead th { + text-align: start; + white-space: nowrap; + font-size: 12px; +} + +.table th, +.table td { + padding: 15px; + text-align: left; + border-bottom: 0.5px solid var(--col--gray8); +} + +.loadingScreen { + width: 100%; + display: flex; + justify-content: center; +} + +.headerCellHover { + cursor: pointer; +} + +.sortIcon { + margin-bottom: -4px; +} + +.timeTemplate { + display: flex; + flex-direction: column; +} \ No newline at end of file diff --git a/ui/components/organisms/table/index.ts b/ui/components/organisms/table/index.ts new file mode 100644 index 0000000..1a876cf --- /dev/null +++ b/ui/components/organisms/table/index.ts @@ -0,0 +1 @@ +export { default as Table } from './table'; diff --git a/ui/components/organisms/table/table.tsx b/ui/components/organisms/table/table.tsx new file mode 100644 index 0000000..b4dc08d --- /dev/null +++ b/ui/components/organisms/table/table.tsx @@ -0,0 +1,109 @@ +import Image from 'next/image'; +import style from './index.module.css'; +import getCell from './templates'; + +import sortIcon from './img/SortIcon.svg'; +import classNames from 'classnames'; +import { ORDER_BY } from '../../../comman/types'; +import { TableErrorMessage } from '../../atoms/tableErrorMessage'; +import Pagination from '../pagination/pagination'; +import { Loader, LoaderVariant } from '../../atoms/loader'; + +const Table = ({ + data, + config: configs, + isLoading, + currentPage, + pageLimit, + totalElements, + pagesCount, + sortBy, + orderBy, + onChangePage, + limitOptions, + onChangeLimit, + onChangeSort, + onChangeOrder, +}) => { + const handleSort = (sort?: string): void => { + if (!sort) return; + if (sort === sortBy) { + return onChangeOrder(orderBy === ORDER_BY.DESC ? ORDER_BY.ASC : ORDER_BY.DESC); + } + onChangeSort(sort); + onChangeOrder(undefined); + }; + const showErrorMessage = !isLoading && (!data || data?.data?.length < 1 ); + + const renderPagination = () => { + return ( + + ); + }; + + return ( + <> + {renderPagination()} +
+
+ + + {configs.map(({ headerText, sortBy: configSortBy }) => ( + + ))} + + + {!isLoading && !showErrorMessage && ( + + {data?.data?.map((item, index) => { + return ( + + {configs.map((config, index) => { + return ; + })} + + ); + })} + + )} +
handleSort(configSortBy)} + className={classNames('t-inter-semi-bold', { + [style.headerCellHover]: configSortBy, + })} + > + {headerText} + {sortBy === configSortBy && ( + sort + )} +
{getCell({ data: item, config })}
+
+ {showErrorMessage && } + + {isLoading ? ( +
+ +
+ ) : ( + <> {renderPagination()} + )} + + ); +}; + +export default Table; diff --git a/ui/components/organisms/table/templates/accountTemplate/accountTemplate.tsx b/ui/components/organisms/table/templates/accountTemplate/accountTemplate.tsx new file mode 100644 index 0000000..0760743 --- /dev/null +++ b/ui/components/organisms/table/templates/accountTemplate/accountTemplate.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import style from '../index.module.css'; +import AccountName from '../../../../organisms/accountName'; + +const AccountTemplate = ({ data, config }) => { + const pk = data[config.fields?.pk]; + const img = data[config.fields.img]; + const name = data[config.fields.name]; + const view = config.view; + const isPkArray = Array.isArray(pk); + const newImg = isPkArray ? pk[0]?.[config?.fields?.nestedImg] : img; + const newName = isPkArray ? pk[0]?.[config?.fields?.nestedName] : name; + const noRedirectFromValue = config.fields.noRedirectFromValue; + const noRedirectFromData = data[config.fields.noRedirectFromData]; + const redirect = config.fields.getRedirectFromData + ? config.fields.getRedirectFromData(data) + : config.fields.redirect || 'account'; + const noRedirect = noRedirectFromData ?? (noRedirectFromValue ? noRedirectFromValue(pk) : config.fields.noRedirect); + + return ( +
+ config.fields.getRedirectLink(pk, data[config.fields.isValidator]) + : null + } + noRedirect={noRedirect} + /> +
+ ); +}; + +export default AccountTemplate; diff --git a/ui/components/organisms/table/templates/amountTemplate/index.module.css b/ui/components/organisms/table/templates/amountTemplate/index.module.css new file mode 100644 index 0000000..f48af85 --- /dev/null +++ b/ui/components/organisms/table/templates/amountTemplate/index.module.css @@ -0,0 +1,7 @@ +.addionValue { + font-size: 10px; + color: var(--col--gray4); + line-height: 16px; + text-transform: uppercase; + margin-left: 5px; +} diff --git a/ui/components/organisms/table/templates/amountTemplate/index.tsx b/ui/components/organisms/table/templates/amountTemplate/index.tsx new file mode 100644 index 0000000..0c50ef2 --- /dev/null +++ b/ui/components/organisms/table/templates/amountTemplate/index.tsx @@ -0,0 +1,29 @@ +import classNames from 'classnames'; +import styles from './index.module.css'; +import { formatNum } from '../../../../../comman/helpers'; + +type AmountTemplateProps = { + data: any; + config: { + fields: { + value: string; + additionValue?: string; + }; + }; +}; + +const AmountTemplate = ({ data, config }: AmountTemplateProps): JSX.Element => { + const value = data[config.fields.value]; + const additionValue = data[config.fields.additionValue] || config.fields.additionValue; + + return ( +
+ <> + {formatNum(value, 2, true, true)} + {additionValue && {additionValue}} + +
+ ); +}; + +export default AmountTemplate; diff --git a/ui/components/organisms/table/templates/buttonTemplate/buttonTemplate.tsx b/ui/components/organisms/table/templates/buttonTemplate/buttonTemplate.tsx new file mode 100644 index 0000000..0f889d7 --- /dev/null +++ b/ui/components/organisms/table/templates/buttonTemplate/buttonTemplate.tsx @@ -0,0 +1,18 @@ +import { Button } from "../../../../atoms/button"; +import { Variant } from "../../../../atoms/button/types"; + +type ButtonTemplateProps = { + data: any; + config: { + fields: { + value: string; + url: string; + }; + }; +}; +const ButtonTemplate = ({ data, config }: ButtonTemplateProps) => { + const buttonText = config.fields.value; + return