diff --git a/src/App.tsx b/src/App.tsx index 0e57c7bb..776dc3b8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,10 @@ import { ColorModeScript } from '@chakra-ui/react' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { ClientProvider } from '@vocdoni/chakra-components' +import { ExtendedSDKClient } from '@vocdoni/extended-sdk' import { EnvOptions } from '@vocdoni/sdk' -import { RoutesProvider } from './router' import { VocdoniEnvironment } from '~constants' -import { ExtendedSDKClient } from '@vocdoni/extended-sdk' -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { RoutesProvider } from './router' const queryClient = new QueryClient() diff --git a/src/components/Accounts/Card.tsx b/src/components/Accounts/Card.tsx index 7ee0c020..af0e4b61 100644 --- a/src/components/Accounts/Card.tsx +++ b/src/components/Accounts/Card.tsx @@ -4,8 +4,8 @@ import { OrganizationProvider, useOrganization } from '@vocdoni/react-providers' import { Trans, useTranslation } from 'react-i18next' import { generatePath, Link as RouterLink } from 'react-router-dom' import { ReducedTextAndCopy } from '~components/Layout/CopyButton' -import { FallbackAccountImg, RoutePath } from '~constants' import LinkCard from '~components/Layout/LinkCard' +import { FallbackAccountImg, RoutePath } from '~constants' type IAccountCardProps = { id?: string diff --git a/src/components/Accounts/Detail.tsx b/src/components/Accounts/Detail.tsx index c963136e..2e649892 100644 --- a/src/components/Accounts/Detail.tsx +++ b/src/components/Accounts/Detail.tsx @@ -2,16 +2,16 @@ import { Tab, TabList, TabPanel, TabPanels, VStack } from '@chakra-ui/react' import { OrganizationHeader, OrganizationName } from '@vocdoni/chakra-components' import { useOrganization } from '@vocdoni/react-providers' import { Trans, useTranslation } from 'react-i18next' +import AccountFees from '~components/Accounts/Details/Fees' +import AccountTransfers from '~components/Accounts/Details/Transfers' import { ReducedTextAndCopy } from '~components/Layout/CopyButton' import { HeroHeaderLayout } from '~components/Layout/HeroHeaderLayout' import { RouteParamsTabs } from '~components/Layout/RouteParamsTabs' import { RawContentBox } from '~components/Layout/ShowRawButton' +import TextAndTag from '~components/Layout/TextAndTag' import { FallbackHeaderImg, RoutePath } from '~constants' -import AccountTransfers from '~components/Accounts/Details/Transfers' -import AccountElections from './Details/Elections' import AccountDetails from './Details/AccountDetails' -import AccountFees from '~components/Accounts/Details/Fees' -import TextAndTag from '~components/Layout/TextAndTag' +import AccountElections from './Details/Elections' const AccountDetail = () => { const { organization } = useOrganization() diff --git a/src/components/Accounts/Details/AccountDetails.tsx b/src/components/Accounts/Details/AccountDetails.tsx index 2aa12006..a993785a 100644 --- a/src/components/Accounts/Details/AccountDetails.tsx +++ b/src/components/Accounts/Details/AccountDetails.tsx @@ -1,11 +1,11 @@ import { Flex, Icon, Link } from '@chakra-ui/react' import { OrganizationDescription } from '@vocdoni/chakra-components' +import { useOrganization } from '@vocdoni/react-providers' import { ensure0x } from '@vocdoni/sdk' import { Trans, useTranslation } from 'react-i18next' import { FaUserAlt } from 'react-icons/fa' import { DetailsGrid, GridItemProps } from '~components/Layout/DetailsGrid' import { AppBaseURL } from '~constants' -import { useOrganization } from '@vocdoni/react-providers' const AccountDetails = () => { const { t } = useTranslation() diff --git a/src/components/Accounts/Details/Elections.tsx b/src/components/Accounts/Details/Elections.tsx index 7f8850e4..eb165038 100644 --- a/src/components/Accounts/Details/Elections.tsx +++ b/src/components/Accounts/Details/Elections.tsx @@ -1,12 +1,11 @@ import { Flex } from '@chakra-ui/react' +import { RoutedPaginationProvider, useOrganization, useRoutedPagination } from '@vocdoni/react-providers' import { useTranslation } from 'react-i18next' -import { RoutedPaginationProvider, useRoutedPagination } from '~components/Pagination/PaginationProvider' +import { PaginatedAsyncList } from '~components/Layout/AsyncList' +import { NoResultsError } from '~components/Layout/ContentError' import { ElectionCard } from '~components/Process/Card' import { RoutePath } from '~constants' import { useOrganizationElections } from '~queries/accounts' -import { NoResultsError } from '~components/Layout/ContentError' -import { useOrganization } from '@vocdoni/react-providers' -import { PaginatedAsyncList } from '~components/Layout/AsyncList' const AccountElections = () => { const { t } = useTranslation() @@ -29,15 +28,14 @@ const AccountElectionsList = () => { const { page }: { page?: number } = useRoutedPagination() const { organization } = useOrganization() - if (!organization) return null - const { data, isLoading, isError, error } = useOrganizationElections({ - address: organization.address, + address: organization?.address as string, page: page, options: { - enabled: !!organization.address, + enabled: !!organization?.address, }, }) + if (!organization) return null return ( diff --git a/src/components/Accounts/Details/Fees.tsx b/src/components/Accounts/Details/Fees.tsx index d9ebfb08..ddbc2ee1 100644 --- a/src/components/Accounts/Details/Fees.tsx +++ b/src/components/Accounts/Details/Fees.tsx @@ -1,35 +1,30 @@ import { Flex, Link, Skeleton, Td, Text, Th, Thead, Tr } from '@chakra-ui/react' -import { useOrganization } from '@vocdoni/react-providers' +import { PaginationProvider, useOrganization, usePagination } from '@vocdoni/react-providers' import { Fee, TransactionType } from '@vocdoni/sdk' import { Trans } from 'react-i18next' import { generatePath, Link as RouterLink } from 'react-router-dom' import { PaginatedAsyncTable } from '~components/Layout/AsyncList' -import { PaginationProvider, usePagination } from '~components/Pagination/PaginationProvider' import { TransactionTypeBadge } from '~components/Transactions/TransactionCard' import { RoutePath } from '~constants' import { useDateFns } from '~i18n/use-date-fns' import { useAccountFees } from '~queries/accounts' import { generateListStub, PaginationStub } from '~utils/stubs' -const AccountFees = () => { - return ( - - - - ) -} +const AccountFees = () => ( + + + +) const AccountFeesTable = () => { const { page } = usePagination() const { organization } = useOrganization() - if (!organization) return null - - const feesCount = organization.feesCount ?? 0 + const feesCount = organization?.feesCount ?? 0 const { data, isError, error, isPlaceholderData } = useAccountFees({ params: { - accountId: organization.address, + accountId: organization?.address as string, page, }, options: { @@ -48,6 +43,8 @@ const AccountFeesTable = () => { }, }) + if (!organization) return null + return ( { - return ( - - - - ) -} +const AccountTransfers = () => ( + + + +) const AccountTransfersTable = () => { const { page } = usePagination() - const { formatDistance } = useDateFns() - const { t } = useTranslation() const { organization } = useOrganization() - if (!organization) return null - - const txCount = organization.transfersCount ?? 0 + const txCount = organization?.transfersCount ?? 0 const { data, isError, error, isPlaceholderData } = useAccountTransfers({ - address: organization.address, + address: organization?.address as string, page: page, options: { - enabled: txCount > 0, + enabled: !!organization && txCount > 0, placeholderData: { transfers: generateListStub({ amount: 12, @@ -71,6 +63,8 @@ const AccountTransfersTable = () => { }, }) + if (!organization) return null + return ( { const { t } = useTranslation() const navigate = useNavigate() const [blockHeight, setBlockHeight] = useState('') - const { data: stats, isLoading: isLoadingStats } = useChainInfo() + const { data: stats } = useChainInfo() const blockCount = stats?.height || 0 @@ -27,7 +27,7 @@ export const BlocksFilter = () => { throw new Error(t('blocks.invalid_block_search', { defaultValue: 'Must to be a valid block height' })) } navigate(generatePath(RoutePath.Block, { height: num.toString(), tab: null, page: null })) - }, [blockHeight, blockCount]) + }, [blockHeight, blockCount, navigate, t]) return ( { refetchInterval: RefreshIntervalBlocks, }) - const blockCount = stats?.height || 0 - const { data, isLoading: isLoadingBlocks, diff --git a/src/components/Envelope/EnvelopeList.tsx b/src/components/Envelope/EnvelopeList.tsx index 3208ca69..b3d61fd4 100644 --- a/src/components/Envelope/EnvelopeList.tsx +++ b/src/components/Envelope/EnvelopeList.tsx @@ -1,14 +1,13 @@ import { Flex, Grid } from '@chakra-ui/react' -import { useElection } from '@vocdoni/react-providers' +import { Pagination } from '@vocdoni/chakra-components' +import { PaginationProvider, useElection, usePagination } from '@vocdoni/react-providers' import { PublishedElection, VoteSummary } from '@vocdoni/sdk' import { useTranslation } from 'react-i18next' import { ListDataDisplay } from '~components/Layout/AsyncList' import { NoResultsError } from '~components/Layout/ContentError' -import { Pagination } from '~components/Pagination/Pagination' -import { PaginationProvider, usePagination } from '~components/Pagination/PaginationProvider' import { useElectionVotesList } from '~queries/processes' -import { EnvelopeCard } from './EnvelopeCard' import { generateListStub, PaginationStub } from '~utils/stubs' +import { EnvelopeCard } from './EnvelopeCard' export const PaginatedEnvelopeList = () => { const { election: e } = useElection() diff --git a/src/components/Layout/AsyncList.tsx b/src/components/Layout/AsyncList.tsx index 5cbbd93e..31b65391 100644 --- a/src/components/Layout/AsyncList.tsx +++ b/src/components/Layout/AsyncList.tsx @@ -1,15 +1,8 @@ import { Box, Table, TableContainer, Tbody } from '@chakra-ui/react' -import { PaginationResponse } from '@vocdoni/sdk' import { PropsWithChildren, ReactNode, useMemo } from 'react' import { ContentError, NoResultsError } from '~components/Layout/ContentError' import { LoadingCards, SkeletonCardsProps } from '~components/Layout/Loading' -import { Pagination } from '~components/Pagination/Pagination' -import { RoutedPagination } from '~components/Pagination/RoutedPagination' - -type AsyncListPaginationProps = { - pagination?: Pick['pagination'] - routedPagination?: boolean -} +import { AsyncListPaginationProps, PaginatorSelector } from './RoutedPagination' type AsyncListLayoutProps = { elements?: T[] | null | undefined @@ -20,12 +13,6 @@ type AsyncListLayoutProps = { isLoading?: boolean } & PropsWithChildren -const PaginatorSelector = ({ routedPagination = true, pagination }: AsyncListPaginationProps) => { - if (!pagination) return null - if (routedPagination) return - return -} - export const ListDataDisplay = ({ elements, isError, error, noResultsMsg, children }: AsyncListLayoutProps) => { if (isError) { return @@ -50,15 +37,15 @@ export const PaginatedAsyncList = ({ component: React.ComponentType<{ element: T; index: number }> } & AsyncListLayoutProps & AsyncListPaginationProps) => { - if (isLoading) { - return - } - const memoizedComponents = useMemo( () => elements?.map((element, index) => ), - [elements] + [Component, elements] ) + if (isLoading) { + return + } + return ( {memoizedComponents} @@ -84,7 +71,7 @@ export const PaginatedAsyncTable = ({ AsyncListPaginationProps) => { const memoizedComponents = useMemo( () => elements?.map((element, index) => ), - [elements] + [Component, elements] ) return ( diff --git a/src/components/Layout/ContentError.tsx b/src/components/Layout/ContentError.tsx index be294fb6..64175c4f 100644 --- a/src/components/Layout/ContentError.tsx +++ b/src/components/Layout/ContentError.tsx @@ -1,4 +1,4 @@ -import { Alert, AlertIcon, Code, Stack, Text } from '@chakra-ui/react' +import { Alert, AlertIcon, Code, Stack } from '@chakra-ui/react' import { Trans, useTranslation } from 'react-i18next' export const NoResultsError = ({ msg }: { msg?: string }) => { diff --git a/src/components/Layout/CopyButton.tsx b/src/components/Layout/CopyButton.tsx index f2470340..6cc67b87 100644 --- a/src/components/Layout/CopyButton.tsx +++ b/src/components/Layout/CopyButton.tsx @@ -64,8 +64,9 @@ export const ReducedTextAndCopy = ({ ...rest }: ReducedTextAndCopyProps) => { let text = children + const bpv = useBreakpointValue(breakPoint) // If breakpoint is true and the length of the string is more than 13 it shorts the string - if (breakPoint && useBreakpointValue(breakPoint) && children.length > 13) { + if (breakPoint && bpv && children.length > 13) { text = shortStr(children) } diff --git a/src/components/Layout/IconLink.tsx b/src/components/Layout/IconLink.tsx index d7393901..4be67a90 100644 --- a/src/components/Layout/IconLink.tsx +++ b/src/components/Layout/IconLink.tsx @@ -1,8 +1,8 @@ -import { Box, Flex, Icon, IconProps, Link, Text } from '@chakra-ui/react' -import { generatePath, Link as RouterLink } from 'react-router-dom' +import { Box, Flex, Icon, IconProps, Link } from '@chakra-ui/react' import { PropsWithChildren } from 'react' -import { RoutePath } from '~constants' import { IconType } from 'react-icons' +import { generatePath, Link as RouterLink } from 'react-router-dom' +import { RoutePath } from '~constants' import { Icons } from '~src/theme/components/Icons' export const TxIconLink = ({ block, index }: { block: number; index: number }) => ( diff --git a/src/components/Layout/RouteParamsTabs.tsx b/src/components/Layout/RouteParamsTabs.tsx index bd995a59..e10bfcd0 100644 --- a/src/components/Layout/RouteParamsTabs.tsx +++ b/src/components/Layout/RouteParamsTabs.tsx @@ -1,9 +1,9 @@ +import { Tabs } from '@chakra-ui/react' import { TabsProps } from '@chakra-ui/tabs/dist/tabs' import { useEffect, useState } from 'react' -import { Tabs } from '@chakra-ui/react' -import useQueryParams from '~src/router/use-query-params' import { generatePath, useLocation, useNavigate, useParams } from 'react-router-dom' import { RoutePath } from '~constants' +import useQueryParams from '~src/router/use-query-params' /** * Reimplementation ob Tabs component to store the selected tab in the query params diff --git a/src/components/Layout/RoutedPagination.tsx b/src/components/Layout/RoutedPagination.tsx new file mode 100644 index 00000000..528a89b9 --- /dev/null +++ b/src/components/Layout/RoutedPagination.tsx @@ -0,0 +1,20 @@ +import { useBreakpointValue } from '@chakra-ui/react' +import { RoutedPagination as CRoutedPagination, Pagination, PaginationProps } from '@vocdoni/chakra-components' +import { PaginationResponse } from '@vocdoni/sdk' + +export type AsyncListPaginationProps = { + pagination?: Pick['pagination'] + routedPagination?: boolean +} + +export const PaginatorSelector = ({ routedPagination = true, pagination }: AsyncListPaginationProps) => { + if (!pagination) return null + if (routedPagination) return + return +} + +export const RoutedPagination = (props: PaginationProps) => { + const maxButtons = useBreakpointValue({ base: 6, lg: 10 }) + + return +} diff --git a/src/components/Layout/ShowRawButton.tsx b/src/components/Layout/ShowRawButton.tsx index db1f2fe6..7fa8a564 100644 --- a/src/components/Layout/ShowRawButton.tsx +++ b/src/components/Layout/ShowRawButton.tsx @@ -13,11 +13,10 @@ import { ModalOverlay, useDisclosure, } from '@chakra-ui/react' -import { Trans } from 'react-i18next' +import { Trans, useTranslation } from 'react-i18next' +import { FaCode } from 'react-icons/fa' import { CopyButtonIcon } from '~components/Layout/CopyButton' import { JsonViewer } from '~components/Layout/JsonViewer' -import { useTranslation } from 'react-i18next' -import { FaCode } from 'react-icons/fa' const ShowRawButton = ({ obj, ...props }: { obj: object } & Omit) => { const { getDisclosureProps, getButtonProps } = useDisclosure() diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx deleted file mode 100644 index e982fc0f..00000000 --- a/src/components/Pagination/Pagination.tsx +++ /dev/null @@ -1,223 +0,0 @@ -import { Button, ButtonGroup, ButtonGroupProps, ButtonProps, Input, InputProps, Text } from '@chakra-ui/react' -import { ReactElement, useMemo, useState } from 'react' -import { Link as RouterLink } from 'react-router-dom' -import { usePagination, useRoutedPagination } from './PaginationProvider' -import { PaginationResponse } from '@vocdoni/sdk' -import { Trans } from 'react-i18next' - -export type PaginationProps = ButtonGroupProps & { - maxButtons?: number | false - buttonProps?: ButtonProps - inputProps?: InputProps -} & PaginationResponse - -type PaginatorButtonProps = { - page: number - currentPage: number -} & ButtonProps - -const PageButton = ({ page, currentPage, ...rest }: PaginatorButtonProps) => ( - -) - -const RoutedPageButton = ({ page, currentPage, to, ...rest }: PaginatorButtonProps & { to: string }) => ( - -) - -type EllipsisButtonProps = ButtonProps & { - gotoPage: (page: number) => void - inputProps?: InputProps -} - -const EllipsisButton = ({ gotoPage, inputProps, ...rest }: EllipsisButtonProps) => { - const [ellipsisInput, setEllipsisInput] = useState(false) - - if (ellipsisInput) { - return ( - { - if (e.target instanceof HTMLInputElement && e.key === 'Enter') { - const pageNumber = Number(e.target.value) - gotoPage(pageNumber) - setEllipsisInput(false) - } - }} - onBlur={() => setEllipsisInput(false)} - autoFocus - /> - ) - } - - return ( - - ) -} - -type CreatePageButtonType = (i: number) => ReactElement -type GotoPageType = (page: number) => void - -const usePaginationPages = ( - currentPage: number, - totalPages: number | undefined, - maxButtons: number | undefined | false, - gotoPage: GotoPageType, - createPageButton: CreatePageButtonType, - inputProps?: InputProps, - buttonProps?: ButtonProps -) => { - return useMemo(() => { - if (totalPages === undefined) return [] - - let pages: ReactElement[] = [] - - // Create an array of all page buttons - for (let i = 0; i < totalPages; i++) { - pages.push(createPageButton(i)) - } - - if (!maxButtons || totalPages <= maxButtons) { - return pages - } - - const startEllipsis = ( - - ) - const endEllipsis = ( - - ) - - // Add ellipsis and slice the array accordingly - const sideButtons = 2 // First and last page - const availableButtons = maxButtons - sideButtons // Buttons we can distribute around the current page - - if (currentPage <= availableButtons / 2) { - // Near the start - return [...pages.slice(0, availableButtons), endEllipsis, pages[totalPages - 1]] - } else if (currentPage >= totalPages - 1 - availableButtons / 2) { - // Near the end - return [pages[0], startEllipsis, ...pages.slice(totalPages - availableButtons, totalPages)] - } else { - // In the middle - const startPage = currentPage - Math.floor((availableButtons - 1) / 2) - const endPage = currentPage + Math.floor(availableButtons / 2) - return [pages[0], startEllipsis, ...pages.slice(startPage, endPage - 1), endEllipsis, pages[totalPages - 1]] - } - }, [currentPage, totalPages, maxButtons, gotoPage]) -} - -const PaginationButtons = ({ - totalPages, - totalItems, - currentPage, - goToPage, - createPageButton, - maxButtons = 10, - buttonProps, - ...rest -}: { - totalPages: number | undefined - totalItems: number | undefined - currentPage: number - createPageButton: CreatePageButtonType - goToPage: GotoPageType -} & ButtonGroupProps & - Pick) => { - const pages = usePaginationPages( - currentPage, - totalPages, - maxButtons ? Math.max(5, maxButtons) : false, - (page) => { - if (page >= 0 && totalPages && page < totalPages) { - goToPage(page) - } - }, - createPageButton - ) - - return ( - <> - - {totalPages === undefined ? ( - <> - - - - ) : ( - pages - )} - - {totalItems && ( - - - Showing a total of {{ count: totalItems }} results - - - )} - - ) -} - -export const Pagination = ({ maxButtons = 10, buttonProps, inputProps, pagination, ...rest }: PaginationProps) => { - const { setPage } = usePagination() - const totalPages = pagination.lastPage + 1 - const page = pagination.currentPage - - return ( - setPage(page)} - createPageButton={(i) => ( - setPage(i)} {...buttonProps} /> - )} - currentPage={page} - totalPages={totalPages} - totalItems={pagination.totalItems} - {...rest} - /> - ) -} - -export const RoutedPagination = ({ maxButtons = 10, buttonProps, pagination, ...rest }: PaginationProps) => { - const { getPathForPage, setPage } = useRoutedPagination() - - const totalPages = pagination.lastPage + 1 - const currentPage = pagination.currentPage - - return ( - setPage(page)} - createPageButton={(i) => ( - - )} - currentPage={currentPage} - totalPages={totalPages} - totalItems={pagination.totalItems} - {...rest} - /> - ) -} diff --git a/src/components/Pagination/PaginationProvider.tsx b/src/components/Pagination/PaginationProvider.tsx deleted file mode 100644 index 02261f36..00000000 --- a/src/components/Pagination/PaginationProvider.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { createContext, PropsWithChildren, useCallback, useContext, useState } from 'react' -import { generatePath, useLocation, useNavigate, useParams } from 'react-router-dom' - -export type PaginationContextProps = { - page: number - setPage: (page: number) => void -} - -export type RoutedPaginationContextProps = Omit & { - path: string - // Util function that generates the path for a given page - // (it return the actual path with queryParams and other route params but changing the page) - getPathForPage: (page: number, queryParams?: string) => string - setPage: (page: number, queryParams?: string) => void -} - -const PaginationContext = createContext(undefined) -const RoutedPaginationContext = createContext(undefined) - -export const usePagination = (): PaginationContextProps => { - const context = useContext(PaginationContext) - if (!context) { - throw new Error('usePagination must be used within a PaginationProvider') - } - return context -} - -export const useRoutedPagination = (): RoutedPaginationContextProps => { - const context = useContext(RoutedPaginationContext) - if (!context) { - throw new Error('useRoutedPagination must be used within a RoutedPaginationProvider') - } - return context -} - -export type PaginationProviderProps = {} - -export type RoutedPaginationProviderProps = PaginationProviderProps & { - path: string -} - -export const RoutedPaginationProvider = ({ path, ...rest }: PropsWithChildren) => { - const { search } = useLocation() - const { page, ...extraParams }: { page?: number } = useParams() - const p = page && page > 0 ? page - 1 : 0 - - const navigate = useNavigate() - - const getPathForPage = (page: number, queryParams?: string) => { - const p = queryParams || search - return generatePath(path, { page, ...extraParams }) + p - } - - const setPage = (page: number, queryParams?: string) => { - navigate(getPathForPage(page, queryParams)) - } - - return -} - -export const PaginationProvider = ({ ...rest }: PropsWithChildren) => { - const [page, setPage] = useState(0) - - return -} diff --git a/src/components/Pagination/RoutedPagination.tsx b/src/components/Pagination/RoutedPagination.tsx deleted file mode 100644 index 3015b790..00000000 --- a/src/components/Pagination/RoutedPagination.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { useBreakpointValue } from '@chakra-ui/react' -import { RoutedPagination as Pagination, PaginationProps } from './Pagination' - -// Note this component is a custom definition of the pagination component that will end in chakra-components -export const RoutedPagination = (props: PaginationProps) => { - const maxButtons = useBreakpointValue({ base: 6, lg: 10 }) - - return -} diff --git a/src/components/Process/ProcessList.tsx b/src/components/Process/ProcessList.tsx index a43ea101..431ab801 100644 --- a/src/components/Process/ProcessList.tsx +++ b/src/components/Process/ProcessList.tsx @@ -12,18 +12,18 @@ import { PopoverTrigger, } from '@chakra-ui/react' import { keepPreviousData } from '@tanstack/react-query' +import { useRoutedPagination } from '@vocdoni/react-providers' import { FetchElectionsParameters } from '@vocdoni/sdk' +import { useState } from 'react' import { Trans, useTranslation } from 'react-i18next' +import { LuListFilter } from 'react-icons/lu' +import { PaginatedAsyncList } from '~components/Layout/AsyncList' import { InputSearch } from '~components/Layout/Inputs' -import { useRoutedPagination } from '~components/Pagination/PaginationProvider' import { useProcessList } from '~queries/processes' +import { useRoutedPaginationQueryParams } from '~src/router/use-query-params' import { isEmpty } from '~utils/objects' -import { ElectionCard } from './Card' -import { LuListFilter } from 'react-icons/lu' import { isValidPartialProcessId } from '~utils/strings' -import { useState } from 'react' -import { useRoutedPaginationQueryParams } from '~src/router/use-query-params' -import { PaginatedAsyncList } from '~components/Layout/AsyncList' +import { ElectionCard } from './Card' type FilterQueryParams = { [K in keyof Omit]: string diff --git a/src/components/Stats/ChainDetails/ChainInfo.tsx b/src/components/Stats/ChainDetails/ChainInfo.tsx index 9335d86e..960eb50b 100644 --- a/src/components/Stats/ChainDetails/ChainInfo.tsx +++ b/src/components/Stats/ChainDetails/ChainInfo.tsx @@ -1,12 +1,12 @@ import { Badge, HStack, Text, VStack } from '@chakra-ui/react' import { Trans, useTranslation } from 'react-i18next' -import { useChainInfo } from '~queries/stats' -import { useDateFns } from '~i18n/use-date-fns' import { MdSpeed } from 'react-icons/md' import { DetailsGrid, GridItemProps } from '~components/Layout/DetailsGrid' -import { StatsCardWrapper } from '~components/Stats/StatsCardWrapper' -import { TxCostsModal } from '~components/Stats/ChainDetails/TxCosts' import { PriceFactorsModal } from '~components/Stats/ChainDetails/PriceFactors' +import { TxCostsModal } from '~components/Stats/ChainDetails/TxCosts' +import { StatsCardWrapper } from '~components/Stats/StatsCardWrapper' +import { useDateFns } from '~i18n/use-date-fns' +import { useChainInfo } from '~queries/stats' const SyncBadge = ({ syncing }: { syncing: boolean }) => { const { t } = useTranslation() diff --git a/src/components/Stats/ChainDetails/PriceFactors.tsx b/src/components/Stats/ChainDetails/PriceFactors.tsx index 269b813d..35ad39bb 100644 --- a/src/components/Stats/ChainDetails/PriceFactors.tsx +++ b/src/components/Stats/ChainDetails/PriceFactors.tsx @@ -1,29 +1,10 @@ -import { useChainCosts } from '~queries/stats' +import { Text, VStack } from '@chakra-ui/react' import { useTranslation } from 'react-i18next' import { IoIosPricetag } from 'react-icons/io' -import { - Box, - Button, - HStack, - Icon, - IconButton, - Link, - Modal, - ModalBody, - ModalCloseButton, - ModalContent, - ModalFooter, - ModalHeader, - ModalOverlay, - Text, - useDisclosure, - VStack, -} from '@chakra-ui/react' -import { DetailsGrid } from '~components/Layout/DetailsGrid' -import { Icons } from '~src/theme/components/Icons' import { ContentError } from '~components/Layout/ContentError' -import { RawModal } from '~components/Layout/ShowRawButton' +import { DetailsGrid } from '~components/Layout/DetailsGrid' import { StatsModalWrapper } from '~components/Stats/StatsCardWrapper' +import { useChainCosts } from '~queries/stats' export const PriceFactorsModal = () => { const { t } = useTranslation() diff --git a/src/components/Stats/ChainDetails/StatsCards.tsx b/src/components/Stats/ChainDetails/StatsCards.tsx index aa068b6a..fa0c5544 100644 --- a/src/components/Stats/ChainDetails/StatsCards.tsx +++ b/src/components/Stats/ChainDetails/StatsCards.tsx @@ -1,12 +1,12 @@ -import { IconType } from 'react-icons' import { Box, Card, CardBody, Flex, Grid, Heading, Icon, Link, Stack, Text } from '@chakra-ui/react' -import { generatePath, Link as RouterLink } from 'react-router-dom' import { useEffect, useState } from 'react' -import { useChainInfo } from '~queries/stats' -import { RefreshIntervalBlocks, RoutePath } from '~constants' import { useTranslation } from 'react-i18next' -import { Icons } from '~src/theme/components/Icons' +import { IconType } from 'react-icons' +import { generatePath, Link as RouterLink } from 'react-router-dom' import { ContentError } from '~components/Layout/ContentError' +import { RefreshIntervalBlocks, RoutePath } from '~constants' +import { useChainInfo } from '~queries/stats' +import { Icons } from '~src/theme/components/Icons' interface IStatsCardProps { title: string diff --git a/src/components/Stats/ChainDetails/TxCosts.tsx b/src/components/Stats/ChainDetails/TxCosts.tsx index 35fb27f1..4b96d636 100644 --- a/src/components/Stats/ChainDetails/TxCosts.tsx +++ b/src/components/Stats/ChainDetails/TxCosts.tsx @@ -1,8 +1,8 @@ -import { useChainCosts, useTxsCosts } from '~queries/stats' import { useTranslation } from 'react-i18next' -import { Icons } from '~src/theme/components/Icons' import { DetailsGrid, GridItemProps } from '~components/Layout/DetailsGrid' import { StatsModalWrapper } from '~components/Stats/StatsCardWrapper' +import { useTxsCosts } from '~queries/stats' +import { Icons } from '~src/theme/components/Icons' export const TxCostsModal = () => { const { t } = useTranslation() diff --git a/src/components/Stats/StatsCardWrapper.tsx b/src/components/Stats/StatsCardWrapper.tsx index 44b4e155..dad07048 100644 --- a/src/components/Stats/StatsCardWrapper.tsx +++ b/src/components/Stats/StatsCardWrapper.tsx @@ -23,12 +23,9 @@ import { } from '@chakra-ui/react' import { PropsWithChildren } from 'react' import { IconType } from 'react-icons' -import { RawModal } from '~components/Layout/ShowRawButton' import { ContentError, ContentErrorType } from '~components/Layout/ContentError' -import { useTranslation } from 'react-i18next/index' -import { useChainCosts } from '~queries/stats' +import { RawModal } from '~components/Layout/ShowRawButton' import { Icons } from '~src/theme/components/Icons' -import { IoIosPricetag } from 'react-icons/io' interface StatisticsCardProps { title: string diff --git a/src/components/Stats/index.tsx b/src/components/Stats/index.tsx index df5d6cad..774d8ac4 100644 --- a/src/components/Stats/index.tsx +++ b/src/components/Stats/index.tsx @@ -1,9 +1,9 @@ -import { Flex, VStack } from '@chakra-ui/react' +import { Flex } from '@chakra-ui/react' import { useTranslation } from 'react-i18next' import { VscGraphLine } from 'react-icons/vsc' -import { LatestBlocks } from '~components/Stats/LatestBlocks' import { ChainInfo } from '~components/Stats/ChainDetails/ChainInfo' import { StatsCards } from '~components/Stats/ChainDetails/StatsCards' +import { LatestBlocks } from '~components/Stats/LatestBlocks' import { StatsCardWrapper } from '~components/Stats/StatsCardWrapper' const Stats = () => { diff --git a/src/components/Transactions/TransactionList.tsx b/src/components/Transactions/TransactionList.tsx index a86f2338..fdef979f 100644 --- a/src/components/Transactions/TransactionList.tsx +++ b/src/components/Transactions/TransactionList.tsx @@ -1,12 +1,12 @@ import { Flex } from '@chakra-ui/react' import { keepPreviousData } from '@tanstack/react-query' +import { RoutedPaginationProvider, useRoutedPagination } from '@vocdoni/react-providers' import { IChainTxListResponse } from '@vocdoni/sdk' import { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import { generatePath, useNavigate } from 'react-router-dom' import { PaginatedAsyncList } from '~components/Layout/AsyncList' import { PopoverInputSearch } from '~components/Layout/Inputs' -import { RoutedPaginationProvider, useRoutedPagination } from '~components/Pagination/PaginationProvider' import { TransactionCard } from '~components/Transactions/TransactionCard' import { RoutePath } from '~constants' import { useBlockTransactions } from '~queries/blocks' @@ -28,7 +28,7 @@ export const TransactionFilter = () => { throw new Error(t('transactions.invalid_tx_search', { defaultValue: 'Must to be a valid tx hash' })) } navigate(generatePath(RoutePath.TransactionByHash, { hash: txHash, tab: null })) - }, [txHash, data]) + }, [data, txHash, navigate, t]) return ( { return { diff --git a/src/components/Validators/Detail.tsx b/src/components/Validators/Detail.tsx index 908d824d..79c242ec 100644 --- a/src/components/Validators/Detail.tsx +++ b/src/components/Validators/Detail.tsx @@ -1,13 +1,13 @@ import { Flex, Heading, HStack, Tab, TabList, TabPanel, TabPanels, Text, VStack } from '@chakra-ui/react' import { ensure0x, IChainValidator } from '@vocdoni/sdk' import { Trans, useTranslation } from 'react-i18next' +import { generatePath } from 'react-router-dom' +import { ReducedTextAndCopy } from '~components/Layout/CopyButton' import { DetailsGrid, GridItemProps } from '~components/Layout/DetailsGrid' +import { BlockIconLink } from '~components/Layout/IconLink' import { RouteParamsTabs } from '~components/Layout/RouteParamsTabs' import { RawContentBox } from '~components/Layout/ShowRawButton' -import { ReducedTextAndCopy } from '~components/Layout/CopyButton' -import { BlockIconLink } from '~components/Layout/IconLink' import { ValidatorName } from '~components/Validators/ValidatorCard' -import { generatePath } from 'react-router-dom' import { RoutePath } from '~constants' const DetailsTab = ({ validator }: { validator: IChainValidator }) => { diff --git a/src/components/Validators/ValidatorCard.tsx b/src/components/Validators/ValidatorCard.tsx index 0c9bf51d..f0eeb6dc 100644 --- a/src/components/Validators/ValidatorCard.tsx +++ b/src/components/Validators/ValidatorCard.tsx @@ -1,10 +1,10 @@ import { CardBody, Flex, HStack, Text } from '@chakra-ui/react' +import { IChainValidator } from '@vocdoni/sdk' import { Trans } from 'react-i18next' -import { ReducedTextAndCopy } from '~components/Layout/CopyButton' import { generatePath } from 'react-router-dom' -import { RoutePath } from '~constants' +import { ReducedTextAndCopy } from '~components/Layout/CopyButton' import LinkCard from '~components/Layout/LinkCard' -import { IChainValidator } from '@vocdoni/sdk' +import { RoutePath } from '~constants' export const ValidatorName = ({ name, useCopy, address }: { name?: string; useCopy?: boolean; address: string }) => { const showName = !!name diff --git a/src/components/Verify/index.tsx b/src/components/Verify/index.tsx index 3027091a..2afc357d 100644 --- a/src/components/Verify/index.tsx +++ b/src/components/Verify/index.tsx @@ -1,10 +1,10 @@ -import addVote from '/images/add-vote.svg' import { Box, Button, Flex, Image, Text } from '@chakra-ui/react' import { useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import { generatePath, useNavigate, useParams } from 'react-router-dom' import { InputSearch } from '~components/Layout/Inputs' import { RoutePath } from '~constants' +import addVote from '/images/add-vote.svg' const SearchVote = ({ compact }: { compact?: boolean }) => { const { verifier: urlVerifier }: { verifier?: string } = useParams() diff --git a/src/main.tsx b/src/main.tsx index 388ebe3d..b5c0b6f3 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -2,10 +2,10 @@ import { ChakraProvider } from '@chakra-ui/react' import { StrictMode } from 'react' import * as ReactDOM from 'react-dom/client' import { App } from './App' +import './i18n' import reportWebVitals from './reportWebVitals' import * as serviceWorker from './serviceWorker' import theme from './theme' -import './i18n' const container = document.getElementById('root') if (!container) throw new Error('Failed to find the root element') diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 97956c68..22dbde50 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,6 +1,6 @@ -import LandingPage from '~components/Home' -import { useLoaderData } from 'react-router-dom' import { IChainGetInfoResponse } from '@vocdoni/sdk' +import { useLoaderData } from 'react-router-dom' +import LandingPage from '~components/Home' import { useChainInfo } from '~queries/stats' const Home = () => { diff --git a/src/pages/accounts.tsx b/src/pages/accounts.tsx index 5b30eb2d..1268c7e2 100644 --- a/src/pages/accounts.tsx +++ b/src/pages/accounts.tsx @@ -1,9 +1,9 @@ +import { RoutedPaginationProvider } from '@vocdoni/react-providers' +import { useTranslation } from 'react-i18next' import { AccountsFilter, AccountsList } from '~components/Accounts/List' import ListPageLayout from '~components/Layout/ListPageLayout' -import { useOrganizationCount } from '~queries/accounts' -import { useTranslation } from 'react-i18next' import { RefreshIntervalPagination, RoutePath } from '~constants' -import { RoutedPaginationProvider } from '~components/Pagination/PaginationProvider' +import { useOrganizationCount } from '~queries/accounts' const OrganizationList = () => { const { t } = useTranslation() diff --git a/src/pages/block.tsx b/src/pages/block.tsx index d404f54b..21a9bf6d 100644 --- a/src/pages/block.tsx +++ b/src/pages/block.tsx @@ -1,6 +1,6 @@ -import { BlockDetail as BlockDetailView } from '~components/Blocks/Detail' -import { useLoaderData } from 'react-router-dom' import { IChainBlockInfoResponse } from '@vocdoni/sdk' +import { useLoaderData } from 'react-router-dom' +import { BlockDetail as BlockDetailView } from '~components/Blocks/Detail' const BlockDetail = () => { const block = useLoaderData() as IChainBlockInfoResponse diff --git a/src/pages/blocks.tsx b/src/pages/blocks.tsx index dd81ea88..faae80bf 100644 --- a/src/pages/blocks.tsx +++ b/src/pages/blocks.tsx @@ -1,7 +1,7 @@ -import ListPageLayout from '~components/Layout/ListPageLayout' import { useTranslation } from 'react-i18next' -import { useChainInfo } from '~queries/stats' import { BlocksFilter, PaginatedBlocksList } from '~components/Blocks/BlocksList' +import ListPageLayout from '~components/Layout/ListPageLayout' +import { useChainInfo } from '~queries/stats' const BlocksList = () => { const { t } = useTranslation() diff --git a/src/pages/processes.tsx b/src/pages/processes.tsx index fc11a036..e8852aea 100644 --- a/src/pages/processes.tsx +++ b/src/pages/processes.tsx @@ -1,13 +1,13 @@ -import ListPageLayout from '~components/Layout/ListPageLayout' +import { RoutedPaginationProvider } from '@vocdoni/react-providers' import { useTranslation } from 'react-i18next' -import { useProcessesCount } from '~queries/processes' +import ListPageLayout from '~components/Layout/ListPageLayout' import { ProcessList as PaginatedProcessList, ProcessByTypeFilter, ProcessSearchBox, } from '~components/Process/ProcessList' import { RefreshIntervalPagination, RoutePath } from '~constants' -import { RoutedPaginationProvider } from '~components/Pagination/PaginationProvider' +import { useProcessesCount } from '~queries/processes' const ProcessList = () => { const { t } = useTranslation() diff --git a/src/pages/transaction.tsx b/src/pages/transaction.tsx index 883da2e1..bf7b2bde 100644 --- a/src/pages/transaction.tsx +++ b/src/pages/transaction.tsx @@ -1,6 +1,6 @@ +import { ErrTransactionNotFound, Tx } from '@vocdoni/sdk' import { useLoaderData } from 'react-router-dom' import { TransactionDetail as TransactionDetailView } from '~components/Transactions/Detail' -import { ErrTransactionNotFound, Tx } from '@vocdoni/sdk' const TransactionDetail = () => { const tx = useLoaderData() as Tx diff --git a/src/pages/transactions.tsx b/src/pages/transactions.tsx index 44c2622f..9b673a0c 100644 --- a/src/pages/transactions.tsx +++ b/src/pages/transactions.tsx @@ -1,8 +1,8 @@ -import ListPageLayout from '~components/Layout/ListPageLayout' import { useTranslation } from 'react-i18next' +import ListPageLayout from '~components/Layout/ListPageLayout' import { PaginatedTransactionList, TransactionFilter } from '~components/Transactions/TransactionList' -import { useTransactionsCount } from '~queries/transactions' import { RefreshIntervalPagination } from '~constants' +import { useTransactionsCount } from '~queries/transactions' const TransactionsList = () => { const { t } = useTranslation() diff --git a/src/pages/validator.tsx b/src/pages/validator.tsx index a98bc2fb..4a0211be 100644 --- a/src/pages/validator.tsx +++ b/src/pages/validator.tsx @@ -1,5 +1,5 @@ -import { useLoaderData, useParams } from 'react-router-dom' import { ensure0x, IChainValidator, IChainValidatorsListResponse } from '@vocdoni/sdk' +import { useLoaderData, useParams } from 'react-router-dom' import { ValidatorDetail } from '~components/Validators/Detail' const Validator = () => { diff --git a/src/pages/validators.tsx b/src/pages/validators.tsx index 1f5f21cb..9ba2d0da 100644 --- a/src/pages/validators.tsx +++ b/src/pages/validators.tsx @@ -1,9 +1,9 @@ -import ListPageLayout from '~components/Layout/ListPageLayout' +import { IChainValidatorsListResponse } from '@vocdoni/sdk' import { useTranslation } from 'react-i18next' import { useLoaderData } from 'react-router-dom' -import { IChainValidatorsListResponse } from '@vocdoni/sdk' -import { ValidatorCard } from '~components/Validators/ValidatorCard' import { PaginatedAsyncList } from '~components/Layout/AsyncList' +import ListPageLayout from '~components/Layout/ListPageLayout' +import { ValidatorCard } from '~components/Validators/ValidatorCard' const Validators = () => { const validators = (useLoaderData() as IChainValidatorsListResponse).validators diff --git a/src/pages/verify.tsx b/src/pages/verify.tsx index 082290d4..1218f33e 100644 --- a/src/pages/verify.tsx +++ b/src/pages/verify.tsx @@ -1,11 +1,11 @@ -import { useParams } from 'react-router-dom' -import { useVoteInfo } from '~queries/vote' -import { VerifyForm, VerifyFormMinified } from '~components/Verify' -import { Loading } from '~components/Layout/Loading' import { Flex, Heading } from '@chakra-ui/react' import { Trans } from 'react-i18next' +import { useParams } from 'react-router-dom' import EnvelopeDetail from '~components/Envelope/Detail' +import { Loading } from '~components/Layout/Loading' +import { VerifyForm, VerifyFormMinified } from '~components/Verify' import { RoutePath } from '~constants' +import { useVoteInfo } from '~queries/vote' const Verify = () => { const { verifier }: { verifier?: string } = useParams() diff --git a/src/queries/processes.ts b/src/queries/processes.ts index 1407b065..eaecc8a8 100644 --- a/src/queries/processes.ts +++ b/src/queries/processes.ts @@ -8,9 +8,9 @@ import { IElectionKeysResponse, IVoteListResponse, } from '@vocdoni/sdk' +import { PaginationItemsPerPage } from '~constants' import { useChainInfo, useChainInfoOptions } from '~queries/stats' import { isValidPartialProcessId } from '~utils/strings' -import { PaginationItemsPerPage } from '~constants' export const useProcessList = ({ filters, diff --git a/src/queries/transactions.ts b/src/queries/transactions.ts index cf788db5..d8f8b70f 100644 --- a/src/queries/transactions.ts +++ b/src/queries/transactions.ts @@ -1,8 +1,8 @@ -import { useChainInfo, useChainInfoOptions } from '~queries/stats' import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { FetchTransactionsParametersWithPagination, IChainTxListResponse } from '@vocdoni/sdk' -import { useClient } from '@vocdoni/react-providers' import { ExtendedSDKClient } from '@vocdoni/extended-sdk' +import { useClient } from '@vocdoni/react-providers' +import { FetchTransactionsParametersWithPagination, IChainTxListResponse } from '@vocdoni/sdk' +import { useChainInfo, useChainInfoOptions } from '~queries/stats' export const useTransactionList = ({ params, diff --git a/src/queries/vote.ts b/src/queries/vote.ts index f0dbddd5..48bb12a6 100644 --- a/src/queries/vote.ts +++ b/src/queries/vote.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { VoteInfoResponse } from '@vocdoni/sdk' -import { useClient } from '@vocdoni/react-providers' import { ExtendedSDKClient } from '@vocdoni/extended-sdk' +import { useClient } from '@vocdoni/react-providers' +import { VoteInfoResponse } from '@vocdoni/sdk' export const useVoteInfo = ({ verifier, diff --git a/src/router/errors/ElectionError.tsx b/src/router/errors/ElectionError.tsx index 11a9f731..50863bc6 100644 --- a/src/router/errors/ElectionError.tsx +++ b/src/router/errors/ElectionError.tsx @@ -1,9 +1,8 @@ -import { Flex, Heading, Text } from '@chakra-ui/react' +import { Flex, Heading } from '@chakra-ui/react' import { useParams, useRouteError } from 'react-router-dom' +import { ReducedTextAndCopy } from '~components/Layout/CopyButton' import ShowRawButton from '~components/Layout/ShowRawButton' import RouteError from '~src/router/errors/RouteError' -import { PublishedElection } from '@vocdoni/sdk' -import { ReducedTextAndCopy } from '~components/Layout/CopyButton' export const ElectionError = () => { const error = useRouteError() as Error & { raw?: unknown; electionId: string } diff --git a/src/router/use-query-params.ts b/src/router/use-query-params.ts index fe6d7669..104dd471 100644 --- a/src/router/use-query-params.ts +++ b/src/router/use-query-params.ts @@ -1,6 +1,6 @@ +import { useRoutedPagination } from '@vocdoni/react-providers' import { useMemo } from 'react' import { useLocation, useNavigate } from 'react-router-dom' -import { useRoutedPagination } from '~components/Pagination/PaginationProvider' export type QueryParamsType = Record diff --git a/src/theme/components/Icons.ts b/src/theme/components/Icons.ts index 0538d460..ee952465 100644 --- a/src/theme/components/Icons.ts +++ b/src/theme/components/Icons.ts @@ -1,10 +1,10 @@ import { IconType } from 'react-icons' import { BiTransferAlt } from 'react-icons/bi' -import { HiOutlineCube } from 'react-icons/hi2' -import { IoTimeOutline } from 'react-icons/io5' -import { GrValidate } from 'react-icons/gr' import { FaExternalLinkAlt } from 'react-icons/fa' import { FiInfo } from 'react-icons/fi' +import { GrValidate } from 'react-icons/gr' +import { HiOutlineCube } from 'react-icons/hi2' +import { IoTimeOutline } from 'react-icons/io5' type IconName = 'BlockIcon' | 'TxIcon' | 'ClockIcon' | 'ValidatorIcon' | 'ExternalIcon' | 'InfoIcon' diff --git a/src/theme/components/index.ts b/src/theme/components/index.ts index 1c96f1d8..cb6da072 100644 --- a/src/theme/components/index.ts +++ b/src/theme/components/index.ts @@ -1,3 +1,5 @@ +import Envelope from '~src/theme/components/Envelope' +import { QuestionsTypeBadge } from '~src/theme/components/QuestionsTypeBadge' import Card from './Card' import { ElectionHeader, ElectionTitle } from './Election' import ElectionResults from './ElectionResults' @@ -5,8 +7,6 @@ import Link from './Link' import Questions from './Questions' import Radio from './Radio' import Tag from './Tag' -import Envelope from '~src/theme/components/Envelope' -import { QuestionsTypeBadge } from '~src/theme/components/QuestionsTypeBadge' const components = { Card,