Skip to content

Commit

Permalink
added attestation card view
Browse files Browse the repository at this point in the history
  • Loading branch information
satyajeetkolhapure committed Oct 25, 2024
1 parent 35bcdf1 commit 472c436
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { ChevronRight } from "lucide-react";
import { generatePath, useLocation, useNavigate } from "react-router-dom";
import { useTernaryDarkMode } from "usehooks-ts";

import { Button } from "@/components/Buttons";
import { EButtonType } from "@/components/Buttons/enum";
import { useNetworkContext } from "@/providers/network-provider/context";
import { APP_ROUTES } from "@/routes/constants";
import { parseDateTime } from "@/utils/dateUtils";

import { IAttestationCardProps } from "./interface";

export const AttestationCard: React.FC<IAttestationCardProps> = ({
id,
logo,
logoDark,
name,
description,
issuerName,
issuanceDate,
}) => {
const {
network: { network },
} = useNetworkContext();
const navigate = useNavigate();
const location = useLocation();
const { isDarkMode } = useTernaryDarkMode();

const handleViewDetailsClick = (id: string) => {
navigate(generatePath(APP_ROUTES.ATTESTATION_BY_ID, { chainId: network, id }), {
state: { from: location.pathname },
});
};

const displayLogo = () => {
const Logo: React.FC<React.SVGProps<SVGSVGElement>> = isDarkMode && logoDark ? logoDark : logo;
return <Logo className="w-full h-auto max-w-[2.5rem] md:max-w-[3rem] max-h-[2.5rem] md:max-h-[3rem]" />;
};

return (
<div
key={`${id}`}
className="group flex flex-col gap-4 border border-border-card dark:border-border-cardDark rounded-xl p-4 md:p-6 hover:bg-surface-secondary dark:hover:bg-surface-secondaryDark transition md:min-h-[20rem]"
>
<div className="flex items-center gap-3 text-xl md:text-2xl font-semibold text-blackDefault dark:text-whiteDefault">
<div className="w-[2.5rem] h-[2.5rem] md:w-[3rem] md:h-[3rem] flex items-center justify-center">
{displayLogo()}
</div>
{name}
</div>
{description && description.trim() ? (
<div className="text-sm font-normal text-text-darkGrey dark:text-tertiary">{description}</div>
) : null}
<div className="text-sm font-normal text-text-darkGrey dark:text-tertiary">
<span className="font-bold">Issuer : </span>
{issuerName}
</div>
<div className="text-sm font-normal text-text-darkGrey dark:text-tertiary">
<span className="font-bold">Date : </span>
{parseDateTime(issuanceDate.toString(), true).stringUTC}
</div>
<div className="flex flex-1 flex-col lg:flex-row lg:items-end gap-4 justify-end lg:justify-start">
<Button
isSmall
name="View details"
handler={() => handleViewDetailsClick(id)}
buttonType={EButtonType.OUTLINED}
iconRight={<ChevronRight />}
/>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface IAttestationCardProps {
id: string;
logo: React.FC<React.SVGProps<SVGSVGElement>>;
logoDark?: React.FC<React.SVGProps<SVGSVGElement>>;
name: string;
description?: string;
issuerName: string;
issuanceDate: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useEnsName } from "wagmi";

import { Link } from "@/components/Link";
import { useNetworkContext } from "@/providers/network-provider/context";
import { toPortalById } from "@/routes/constants";
import { CHAIN_ID_ROUTE, toAttestationsBySubject, toPortalById } from "@/routes/constants";
import { getBlockExplorerLink } from "@/utils";
import { displayAmountWithComma } from "@/utils/amountUtils";
import { cropString } from "@/utils/stringUtils";
Expand All @@ -17,7 +17,7 @@ import { createDateListItem } from "./utils";

export const AttestationInfo: React.FC<Attestation> = ({ ...attestation }) => {
const {
network: { chain },
network: { chain, network },
} = useNetworkContext();

const { data: attesterEnsAddress } = useEnsName({
Expand Down Expand Up @@ -73,7 +73,7 @@ export const AttestationInfo: React.FC<Attestation> = ({ ...attestation }) => {
{
title: t("attestation.info.subject"),
value: displaySubjectEnsNameOrAddress(),
link: `${blockExplorerLink}/${subject}`,
link: toAttestationsBySubject(subject).replace(CHAIN_ID_ROUTE, network),
},
];

Expand Down
36 changes: 32 additions & 4 deletions explorer/src/pages/MyAttestations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ import { useAccount } from "wagmi";

import { Button } from "@/components/Buttons";
import { EButtonType } from "@/components/Buttons/enum";
import { DataTable } from "@/components/DataTable";
import { InfoBlock } from "@/components/InfoBlock";
import { THOUSAND } from "@/constants";
import { columns } from "@/constants/columns/attestation";
import { EQueryParams } from "@/enums/queryParams";
import useWindowDimensions from "@/hooks/useWindowDimensions";
import { SWRKeys } from "@/interfaces/swr/enum";
import { useNetworkContext } from "@/providers/network-provider/context";
import { APP_ROUTES } from "@/routes/constants";
import { cropString } from "@/utils/stringUtils";

import { AttestationCard } from "../Attestation/components/AttestationCard";
import { TitleAndSwitcher } from "../Attestations/components/TitleAndSwitcher";
import { issuersData } from "../Home/data";
import { IIssuer } from "../Home/interface";

export const MyAttestations: React.FC = () => {
const {
Expand Down Expand Up @@ -91,7 +91,35 @@ export const MyAttestations: React.FC = () => {
) : !attestationsList || !attestationsList.length ? (
<InfoBlock icon={<ArchiveIcon />} message={t("attestation.messages.emptyList")} />
) : (
<DataTable columns={columns({ chain })} data={attestationsList} link={APP_ROUTES.ATTESTATION_BY_ID} />
<div className="flex flex-col gap-14 md:gap-[4.5rem] container mt-14 md:mt-12">
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
{attestationsList.map((attestation) => {
const issuerData = issuersData.find((issuer) =>
issuer.attestationDefinitions.some(
(definition) =>
definition.schema === attestation.schema.id && definition.portal === attestation.portal.id,
),
) as IIssuer;
const attestationDefinitions = issuerData?.attestationDefinitions.find(
(definition) => definition.schema === attestation.schema.id,
);

if (!issuerData) return null;
return (
<AttestationCard
key={attestation.id}
id={attestation.id}
logo={attestationDefinitions?.logo ?? issuerData?.logo}
logoDark={attestationDefinitions?.logoDark ?? issuerData?.logoDark}
name={attestationDefinitions?.name ?? issuerData?.name}
description={attestationDefinitions?.description ?? ""}
issuerName={issuerData.name}
issuanceDate={attestation.attestedDate}
/>
);
})}
</div>
</div>
)}
</TitleAndSwitcher>
);
Expand Down
66 changes: 66 additions & 0 deletions explorer/src/pages/Subject/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { OrderDirection } from "@verax-attestation-registry/verax-sdk/lib/types/.graphclient";
import { useParams } from "react-router-dom";
import useSWR from "swr";

import { EQueryParams } from "@/enums/queryParams";
import { SWRKeys } from "@/interfaces/swr/enum";
import { useNetworkContext } from "@/providers/network-provider/context";

import { AttestationCard } from "../Attestation/components/AttestationCard";
import { issuersData } from "../Home/data";
import { IIssuer } from "../Home/interface";

export const Subject: React.FC = () => {
const { subject } = useParams();
const {
sdk,
network: { chain },
} = useNetworkContext();
const searchParams = new URLSearchParams(window.location.search);
const sortByDateDirection = searchParams.get(EQueryParams.SORT_BY_DATE);

const { data: attestationsList } = useSWR(
`${SWRKeys.GET_ATTESTATION_LIST}/${subject}/${sortByDateDirection}/${chain.id}`,
() =>
sdk.attestation.findBy(
undefined,
undefined,
{ subject },
"attestedDate",
(sortByDateDirection as OrderDirection) || "desc",
),
);

return (
<div className="flex flex-col gap-14 md:gap-[4.5rem] container mt-14 md:mt-12">
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
{attestationsList &&
attestationsList.map((attestation) => {
const issuerData = issuersData.find((issuer) =>
issuer.attestationDefinitions.some(
(definition) =>
definition.schema === attestation.schema.id && definition.portal === attestation.portal.id,
),
) as IIssuer;
const attestationDefinitions = issuerData?.attestationDefinitions.find(
(definition) => definition.schema === attestation.schema.id,
);

if (!issuerData) return null;
return (
<AttestationCard
key={attestation.id}
id={attestation.id}
logo={attestationDefinitions?.logo ?? issuerData?.logo}
logoDark={attestationDefinitions?.logoDark ?? issuerData?.logoDark}
name={attestationDefinitions?.name ?? issuerData?.name}
description={attestationDefinitions?.description ?? ""}
issuerName={issuerData.name}
issuanceDate={attestation.attestedDate}
/>
);
})}
</div>
</div>
);
};
6 changes: 6 additions & 0 deletions explorer/src/routes/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const ID_ROUTE = ":id";
const SUBJECT_ROUTE = ":subject";
export const CHAIN_ID_ROUTE = ":chainId";

export const APP_ROUTES = {
Expand All @@ -15,6 +16,9 @@ export const APP_ROUTES = {
get MY_ATTESTATIONS() {
return this.ATTESTATIONS + "/my_attestations";
},
get ATTESTATIONS_BY_SUBJECT() {
return this.HOME + "/subject/" + SUBJECT_ROUTE;
},
get ATTESTATION_BY_ID() {
return this.ATTESTATIONS + `/${ID_ROUTE}`;
},
Expand All @@ -40,6 +44,8 @@ export const APP_ROUTES = {
} as const;

export const toAttestationById = (id: string) => APP_ROUTES.ATTESTATION_BY_ID.replace(ID_ROUTE, id);
export const toAttestationsBySubject = (subject: string) =>
APP_ROUTES.ATTESTATIONS_BY_SUBJECT.replace(SUBJECT_ROUTE, subject);
export const toSchemaById = (id: string) => APP_ROUTES.SCHEMA_BY_ID.replace(ID_ROUTE, id);
export const toModuleById = (id: string) => APP_ROUTES.MODULES_BY_ID.replace(ID_ROUTE, id);
export const toPortalById = (id: string) => APP_ROUTES.PORTAL_BY_ID.replace(ID_ROUTE, id);
2 changes: 2 additions & 0 deletions explorer/src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Portal } from "@/pages/Portal";
import { Schema } from "@/pages/Schema";
import { Schemas } from "@/pages/Schemas";
import { Search } from "@/pages/Search";
import { Subject } from "@/pages/Subject";
import { Providers } from "@/providers";
import { loaderNetworkProvider } from "@/providers/network-provider/loader";

Expand All @@ -24,6 +25,7 @@ export const router = createBrowserRouter(
<Route path={APP_ROUTES.ISSUER_BY_ID} element={<Issuer />} />
<Route path={APP_ROUTES.ATTESTATIONS} element={<Attestations />} />
<Route path={APP_ROUTES.MY_ATTESTATIONS} element={<MyAttestations />} />
<Route path={APP_ROUTES.ATTESTATIONS_BY_SUBJECT} element={<Subject />} />
<Route path={APP_ROUTES.ATTESTATION_BY_ID} element={<Attestation />} />
<Route path={APP_ROUTES.SCHEMAS} element={<Schemas />} />
<Route path={APP_ROUTES.SCHEMA_BY_ID} element={<Schema />} />
Expand Down
1 change: 0 additions & 1 deletion sdk/src/dataMapper/AttestationDataMapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import BaseDataMapper from "./BaseDataMapper";
import { lineaSepolia } from "viem/chains";
import { PublicClient, WalletClient } from "viem";
import { VeraxSdk } from "../VeraxSdk";
import { off } from "process";

jest.mock("./BaseDataMapper");
jest.mock("../utils/abiCoder");
Expand Down

0 comments on commit 472c436

Please sign in to comment.