Skip to content

Commit

Permalink
Feat: As a User, I want to see more than 10 items per screen (#535)
Browse files Browse the repository at this point in the history
  • Loading branch information
Stasn13 authored Jan 18, 2024
1 parent d9493e7 commit be384e4
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 21 deletions.
3 changes: 2 additions & 1 deletion explorer/src/assets/locales/en/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"noResults": "No Results",
"hasntBeenFound": "hasn`t been found",
"searchNotFound": "Nothing found on <bold>“{{search}}”</bold> search request",
"searchFound": "<bold>{{count}}</bold> results found on <bold>“{{search}}”</bold> search request"
"searchFound": "<bold>{{count}}</bold> results found on <bold>“{{search}}”</bold> search request",
"perPage": "per page"
},
"routes": {
"issuers": "Issuers",
Expand Down
38 changes: 38 additions & 0 deletions explorer/src/components/Pagination/PerPageSelector/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ChevronDown } from "lucide-react";

import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

interface PerPageSelectorProps {
onChange: (val: string | number) => void;
values: string[] | number[];
value: string | number;
}

export const PerPageSelector: React.FC<PerPageSelectorProps> = ({ onChange, values, value }) => {
return (
<div>
<DropdownMenu>
<DropdownMenuTrigger className="DropdownMenuTrigger flex items-center justify-center border text-xs font-semibold text-text-primary dark:text-whiteDefault outline-none w-16 h-8 px-2 rounded-md outline-none dark:border-greyDark hover:border-border-inputFocus dark:focus:border-border-inputFocus dark:hover:border-border-inputFocus rounded-lg transition">
{value}
<ChevronDown className="header-arrow ml-1 w-5 h-6 relative" />
</DropdownMenuTrigger>
<DropdownMenuContent className="flex flex-col-reverse gap-2 bg-surface-primary dark:bg-blackDefault dark:border-border-cardDark">
{values.map((number) => (
<DropdownMenuItem
key={number}
className="flex gap-2 focus:bg-jumbotronLight dark:focus:bg-jumbotronDark dark:text-whiteDefault cursor-pointer transition"
onClick={() => onChange(number)}
>
{number}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
);
};
22 changes: 19 additions & 3 deletions explorer/src/components/Pagination/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { t } from "i18next";
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react";
import { useEffect, useRef } from "react";
import { useEffect, useRef, useState } from "react";
import { useSearchParams } from "react-router-dom";

import { ITEMS_PER_PAGE_DEFAULT } from "@/constants";
Expand All @@ -9,20 +9,26 @@ import { displayAmountWithComma } from "@/utils/amountUtils";
import { pageBySearchParams } from "@/utils/paginationUtils";

import { IPaginationProps } from "./interface";
import { PerPageSelector } from "./PerPageSelector";

export const Pagination = ({ itemsCount, handlePage }: IPaginationProps) => {
const [searchParams, setSearchParams] = useSearchParams();
const currentPage = pageBySearchParams(searchParams, itemsCount);
const [itemsPerPage, setItemsPerPage] = useState<string | number>(
Number(searchParams.get(EQueryParams.ITEMS_PER_PAGE)) || ITEMS_PER_PAGE_DEFAULT,
);
const currentPage = pageBySearchParams(searchParams, itemsCount, Number(itemsPerPage));

useEffect(() => {
handlePage(currentPage);
}, [currentPage, handlePage, searchParams]);

const totalPages = Math.ceil(itemsCount / ITEMS_PER_PAGE_DEFAULT);
const totalPages = Math.ceil(itemsCount / Number(itemsPerPage));

const disablePrev = currentPage === 1;
const disableNext = currentPage === totalPages;

const itemsPerPageValues = [ITEMS_PER_PAGE_DEFAULT, 20, 50, 100];

const inputRef = useRef<HTMLInputElement>(null);

const handlePageChange = (newPage: number) => {
Expand All @@ -33,6 +39,12 @@ export const Pagination = ({ itemsCount, handlePage }: IPaginationProps) => {
}
};

const handleItemsPerPage = (val: number | string) => {
setItemsPerPage(val);
searchParams.set(EQueryParams.ITEMS_PER_PAGE, String(val));
setSearchParams(searchParams);
};

const handleFirstPage = () => handlePageChange(1);
const handleLastPage = () => handlePageChange(totalPages);
const handlePreviousPage = () => handlePageChange(currentPage - 1);
Expand Down Expand Up @@ -85,6 +97,10 @@ export const Pagination = ({ itemsCount, handlePage }: IPaginationProps) => {
className="w-16 h-8 px-2 border text-xs font-semibold dark:bg-transparent text-text-primary dark:text-whiteDefault text-center outline-none border-border-table dark:border-greyDark focus:border-border-inputFocus dark:focus:border-border-inputFocus rounded-lg transition"
/>
<span className="text-slate-500 text-xs font-normal">{`of ${displayAmountWithComma(totalPages)}`}</span>
<PerPageSelector onChange={handleItemsPerPage} values={itemsPerPageValues} value={itemsPerPage} />
<span className="hidden md:inline-block text-slate-500 text-xs font-normal">
{t("common.messages.perPage")}
</span>
</div>
<div className="flex gap-3">
<button
Expand Down
1 change: 1 addition & 0 deletions explorer/src/enums/queryParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export enum EQueryParams {
PAGE = "page",
SORT_BY_DATE = "sort_by_date",
SEARCH_QUERY = "search_query",
ITEMS_PER_PAGE = "page_size",
}
11 changes: 6 additions & 5 deletions explorer/src/pages/Attestations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ export const Attestations: React.FC = () => {
const totalItems = attestationsCount ?? ZERO;
const page = pageBySearchParams(searchParams, totalItems);
const sortByDateDirection = searchParams.get(EQueryParams.SORT_BY_DATE);
const itemsPerPage = Number(searchParams.get(EQueryParams.ITEMS_PER_PAGE)) || ITEMS_PER_PAGE_DEFAULT;

const [skip, setSkip] = useState<number>(getItemsByPage(page));
const [skip, setSkip] = useState<number>(getItemsByPage(page, itemsPerPage));

const { data: attestationsList, isLoading } = useSWR(
`${SWRKeys.GET_ATTESTATION_LIST}/${skip}/${sortByDateDirection}/${chain.id}`,
`${SWRKeys.GET_ATTESTATION_LIST}/${itemsPerPage}/${skip}/${sortByDateDirection}/${chain.id}`,
() =>
sdk.attestation.findBy(
ITEMS_PER_PAGE_DEFAULT,
itemsPerPage,
skip,
undefined,
"attestedDate",
Expand All @@ -49,13 +50,13 @@ export const Attestations: React.FC = () => {
);

const handlePage = (retrievedPage: number) => {
setSkip(getItemsByPage(retrievedPage));
setSkip(getItemsByPage(retrievedPage, itemsPerPage));
};

const columnsSkeletonRef = useRef(columnsSkeleton(columns(), attestationColumnsOption));

const data = isLoading
? { columns: columnsSkeletonRef.current, list: skeletonAttestations() }
? { columns: columnsSkeletonRef.current, list: skeletonAttestations(itemsPerPage) }
: { columns: columns({ sdk, chainId: chain.id }), list: attestationsList || [] };

return (
Expand Down
13 changes: 8 additions & 5 deletions explorer/src/pages/Modules/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Pagination } from "@/components/Pagination";
import { ITEMS_PER_PAGE_DEFAULT, ZERO } from "@/constants";
import { columns, moduleColumnsOption, skeletonModules } from "@/constants/columns/module";
import { columnsSkeleton } from "@/constants/columns/skeleton";
import { EQueryParams } from "@/enums/queryParams";
import { SWRKeys } from "@/interfaces/swr/enum";
import { useNetworkContext } from "@/providers/network-provider/context";
import { APP_ROUTES } from "@/routes/constants";
Expand All @@ -25,20 +26,22 @@ export const Modules: React.FC = () => {
const totalItems = modulesCount ? Number(modulesCount) : ZERO;
const searchParams = new URLSearchParams(window.location.search);
const page = pageBySearchParams(searchParams, totalItems);
const itemsPerPage = Number(searchParams.get(EQueryParams.ITEMS_PER_PAGE)) || ITEMS_PER_PAGE_DEFAULT;

const [skip, setSkip] = useState<number>(getItemsByPage(page));
const [skip, setSkip] = useState<number>(getItemsByPage(page, itemsPerPage));

const { data: modulesList, isLoading } = useSWR(`${SWRKeys.GET_MODULE_LIST}/${skip}/${chain.id}`, () =>
sdk.module.findBy(ITEMS_PER_PAGE_DEFAULT, skip),
const { data: modulesList, isLoading } = useSWR(
`${SWRKeys.GET_MODULE_LIST}/${itemsPerPage}/${skip}/${chain.id}`,
() => sdk.module.findBy(itemsPerPage, skip),
);

const handlePage = (retrievedPage: number) => {
setSkip(getItemsByPage(retrievedPage));
setSkip(getItemsByPage(retrievedPage, itemsPerPage));
};

const columnsSkeletonRef = useRef(columnsSkeleton(columns(), moduleColumnsOption));
const data = isLoading
? { columns: columnsSkeletonRef.current, list: skeletonModules() }
? { columns: columnsSkeletonRef.current, list: skeletonModules(itemsPerPage) }
: { columns: columns({ chainId: chain.id }), list: modulesList || [] };

return (
Expand Down
15 changes: 10 additions & 5 deletions explorer/src/pages/Schemas/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Pagination } from "@/components/Pagination";
import { ITEMS_PER_PAGE_DEFAULT, ZERO } from "@/constants";
import { columns, schemaColumnsOption, skeletonSchemas } from "@/constants/columns/schema";
import { columnsSkeleton } from "@/constants/columns/skeleton";
import { EQueryParams } from "@/enums/queryParams";
import { SWRKeys } from "@/interfaces/swr/enum";
import { useNetworkContext } from "@/providers/network-provider/context";
import { APP_ROUTES } from "@/routes/constants";
Expand All @@ -26,22 +27,26 @@ export const Schemas: React.FC = () => {
const totalItems = schemasCount ? Number(schemasCount) : ZERO;
const searchParams = new URLSearchParams(window.location.search);
const page = pageBySearchParams(searchParams, totalItems);
const itemsPerPage = Number(searchParams.get(EQueryParams.ITEMS_PER_PAGE)) || ITEMS_PER_PAGE_DEFAULT;

const [skip, setSkip] = useState<number>(getItemsByPage(page));
const [skip, setSkip] = useState<number>(getItemsByPage(page, itemsPerPage));

const { data: schemasList, isLoading } = useSWR(`${SWRKeys.GET_SCHEMAS_LIST}/${skip}/${chain.id}`, () =>
sdk.schema.findBy(ITEMS_PER_PAGE_DEFAULT, skip),
const { data: schemasList, isLoading } = useSWR(
`${SWRKeys.GET_SCHEMAS_LIST}/${itemsPerPage}/${skip}/${chain.id}`,
() => sdk.schema.findBy(itemsPerPage, skip),
);

const handlePage = (retrievedPage: number) => {
setSkip(getItemsByPage(retrievedPage));
setSkip(getItemsByPage(retrievedPage, itemsPerPage));
};

const columnsSkeletonRef = useRef(columnsSkeleton(columns(), schemaColumnsOption));
const data = isLoading
? { columns: columnsSkeletonRef.current, list: skeletonSchemas() }
? { columns: columnsSkeletonRef.current, list: skeletonSchemas(itemsPerPage) }
: { columns: columns(), list: schemasList || [] };

console.log("skip: ", skip, page);

return (
<div className="container mt-5 md:mt-8">
<div className="flex flex-col md:flex-row items-start md:items-center justify-between mb-6 md:mb-8 gap-6 md:gap-0">
Expand Down
4 changes: 2 additions & 2 deletions explorer/src/utils/paginationUtils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { CURRENT_PAGE_DEFAULT, ITEMS_PER_PAGE_DEFAULT, ZERO } from "@/constants";
import { EQueryParams } from "@/enums/queryParams";

export const getItemsByPage = (page: number): number =>
page === CURRENT_PAGE_DEFAULT ? ZERO : (page - 1) * ITEMS_PER_PAGE_DEFAULT;
export const getItemsByPage = (page: number, itemsPerPage: number): number =>
page === CURRENT_PAGE_DEFAULT ? ZERO : (page - 1) * itemsPerPage;

export const pageBySearchParams = (
searchParams: URLSearchParams,
Expand Down

0 comments on commit be384e4

Please sign in to comment.