Skip to content

Commit

Permalink
feat(explorer): As an end-user, I want to get more straight-forward i…
Browse files Browse the repository at this point in the history
…nformation out of the issuer details page (#672)

Co-authored-by: Alain Nicolas <alain.nicolas@consensys.net>
Co-authored-by: Arthur <arthur@coeos.xyz>
  • Loading branch information
3 people authored Aug 29, 2024
1 parent acbf663 commit 7d7a2c3
Show file tree
Hide file tree
Showing 29 changed files with 608 additions and 135 deletions.
File renamed without changes
6 changes: 0 additions & 6 deletions explorer/src/assets/issuers/index-network-black.svg

This file was deleted.

6 changes: 0 additions & 6 deletions explorer/src/assets/issuers/index-network.svg

This file was deleted.

File renamed without changes
4 changes: 3 additions & 1 deletion explorer/src/assets/locales/en/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
"next": "Next",
"learnMore": "Learn More",
"getStarted": "Get Started",
"viewMyAttestations": "View My Attestations"
"viewMyAttestations": "View My Attestations",
"getAttestation": "Get Attestations",
"seeAttestations": "See Attestations"
},
"messages": {
"empty": "Empty",
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
92 changes: 92 additions & 0 deletions explorer/src/components/Pagination/Basic/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { t } from "i18next";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { useSearchParams } from "react-router-dom";

import { ITEMS_PER_PAGE_DEFAULT } from "@/constants";
import { EQueryParams } from "@/enums/queryParams";

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

export const BasicPagination = ({ handlePage }: IBasicPaginationProps) => {
const [searchParams, setSearchParams] = useSearchParams();
const [itemsPerPage, setItemsPerPage] = useState<string | number>(
Number(searchParams.get(EQueryParams.ITEMS_PER_PAGE)) || ITEMS_PER_PAGE_DEFAULT,
);
const [currentPage, setCurrentPage] = useState<number>(1);

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

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

const inputRef = useRef<HTMLInputElement>(null);

const handlePageChange = (newPage: number) => {
if (newPage >= 1 && inputRef && inputRef.current) {
inputRef.current.value = newPage.toString();
searchParams.set(EQueryParams.PAGE, newPage.toString());
setSearchParams(searchParams);
setCurrentPage(newPage);
}
};

const handleItemsPerPage = (val: number | string) => {
setItemsPerPage(val);
searchParams.set(EQueryParams.ITEMS_PER_PAGE, String(val));
setSearchParams(searchParams);
};
const handlePreviousPage = () => handlePageChange(currentPage - 1);
const handleNextPage = () => handlePageChange(currentPage + 1);

const changePage = (inputPage: string) => {
const page = Number(inputPage);
inputPage.length && handlePageChange(page);
};

const blurHandler = () => {
!inputRef.current?.value.length && handlePageChange(currentPage);
};

return (
<div className="flex justify-between items-center mt-8">
<div className="flex gap-3">
<button
type="button"
aria-label="Previous"
onClick={handlePreviousPage}
className="flex text-base font-semibold dark:text-whiteDefault hover:opacity-60 transition"
>
<ChevronLeft />
<span className="hidden md:inline-block">{t("common.actions.previous")}</span>
</button>
</div>
<div className="flex items-center gap-3">
<input
type="number"
ref={inputRef}
defaultValue={currentPage}
onBlur={blurHandler}
onChange={(event) => changePage(event.target.value)}
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"
/>
<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
type="button"
aria-label="Next"
onClick={handleNextPage}
className="flex text-base font-semibold dark:text-whiteDefault hover:opacity-60 transition"
>
<span className="hidden md:inline-block">{t("common.actions.next")}</span> <ChevronRight />
</button>
</div>
</div>
);
};
3 changes: 3 additions & 0 deletions explorer/src/components/Pagination/Basic/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IBasicPaginationProps {
handlePage: (page: number) => void;
}
8 changes: 4 additions & 4 deletions explorer/src/config/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import ArbitrumNovaIcon from "@/assets/networks/arbitrum-nova.svg?react";
import ArbitrumSepoliaIcon from "@/assets/networks/arbitrum-sepolia.svg?react";
import ArbitrumIcon from "@/assets/networks/arbitrum.svg?react";
import BaseIconDark from "@/assets/networks/base-dark.svg?react";
import BaseMainnetIcon from "@/assets/networks/base-mainnet.svg?react";
import BaseSepoliaIcon from "@/assets/networks/base-sepolia.svg?react";
import BaseMainnetIcon from "@/assets/networks/base.svg?react";
import BscMainnetIconDark from "@/assets/networks/bsc-dark.svg?react";
import BscMainnetIcon from "@/assets/networks/bsc-mainnet.svg?react";
import BscTestnetIcon from "@/assets/networks/bsc-testnet.svg?react";
import LineaMainnetIconDark from "@/assets/networks/linea-mainnet-dark.svg?react";
import LineaMainnetIcon from "@/assets/networks/linea-mainnet.svg?react";
import BscMainnetIcon from "@/assets/networks/bsc.svg?react";
import LineaMainnetIconDark from "@/assets/networks/linea-dark.svg?react";
import LineaSepoliaIcon from "@/assets/networks/linea-sepolia.svg?react";
import LineaMainnetIcon from "@/assets/networks/linea.svg?react";
import { INetwork } from "@/interfaces/config";

const lineaSepolia = {
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 @@ -3,4 +3,5 @@ export enum EQueryParams {
SORT_BY_DATE = "sort_by_date",
SEARCH_QUERY = "search_query",
ITEMS_PER_PAGE = "page_size",
WHERE = "where",
}
29 changes: 24 additions & 5 deletions explorer/src/pages/Attestations/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { OrderDirection } from "@verax-attestation-registry/verax-sdk/lib/types/.graphclient";
import { Attestation_filter, OrderDirection } from "@verax-attestation-registry/verax-sdk/lib/types/.graphclient";
import { useRef, useState } from "react";
import { useSearchParams } from "react-router-dom";
import useSWR from "swr";

import { DataTable } from "@/components/DataTable";
import { Pagination } from "@/components/Pagination";
import { BasicPagination } from "@/components/Pagination/Basic";
import { ITEMS_PER_PAGE_DEFAULT, ZERO } from "@/constants";
import { attestationColumnsOption, columns, skeletonAttestations } from "@/constants/columns/attestation";
import { columnsSkeleton } from "@/constants/columns/skeleton";
Expand Down Expand Up @@ -32,6 +33,9 @@ export const Attestations: React.FC = () => {
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 where = searchParams.get(EQueryParams.WHERE)
? (JSON.parse(searchParams.get(EQueryParams.WHERE) ?? "") as Attestation_filter)
: undefined;

const [lastID, setLastID] = useState<number>(getItemsByPage(page, itemsPerPage));

Expand All @@ -43,11 +47,14 @@ export const Attestations: React.FC = () => {
sdk.attestation.findBy(
itemsPerPage,
undefined,
(sortByDateDirection as OrderDirection) === null ||
{
...where,
...((sortByDateDirection as OrderDirection) === null ||
(sortByDateDirection as OrderDirection) === undefined ||
(sortByDateDirection as OrderDirection) === ETableSorting.DESC
? { id_lte: buildAttestationId(totalItems - (page - 1) * itemsPerPage, network.prefix) }
: { id_gt: buildAttestationId(lastID, network.prefix) },
? { id_lte: buildAttestationId(totalItems - (page - 1) * itemsPerPage, network.prefix) }
: { id_gt: buildAttestationId(lastID, network.prefix) }),
},
"attestedDate",
(sortByDateDirection as OrderDirection) || ETableSorting.DESC,
),
Expand All @@ -62,10 +69,22 @@ export const Attestations: React.FC = () => {
? { columns: columnsSkeletonRef.current, list: skeletonAttestations(itemsPerPage) }
: { columns: columns({ chain: network.chain }), list: attestationsList || [] };

const renderPagination = () => {
if (attestationsCount) {
if (where) {
return <BasicPagination handlePage={handlePage} />;
} else {
return <Pagination itemsCount={attestationsCount} handlePage={handlePage} />;
}
} else {
return null;
}
};

return (
<TitleAndSwitcher>
<DataTable columns={data.columns} data={data.list} link={APP_ROUTES.ATTESTATION_BY_ID} />
{attestationsCount ? <Pagination itemsCount={attestationsCount} handlePage={handlePage} /> : null}
{renderPagination()}
</TitleAndSwitcher>
);
};
8 changes: 5 additions & 3 deletions explorer/src/pages/Home/components/Issuers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { Issuer } from "../Issuer";
export const Issuers: React.FC = () => {
return (
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
{issuersData.map((issuer) => (
<Issuer issuer={issuer} key={issuer.address} />
))}
{issuersData
.sort((a, b) => a.name.localeCompare(b.name))
.map((issuer) => (
<Issuer issuer={issuer} key={issuer.address} />
))}
</div>
);
};
Loading

0 comments on commit 7d7a2c3

Please sign in to comment.