Skip to content

Commit

Permalink
feat(embed): retrieve stamps via metadata endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
larisa17 committed Jan 30, 2025
1 parent e5184e6 commit b7e90b0
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 183 deletions.
3 changes: 2 additions & 1 deletion src/components/Body/PlatformVerification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import utilStyles from "../../utilStyles.module.css";
import { useEffect, useState } from "react";
import { Buffer } from "buffer";
import { Button } from "../Button";
import { Hyperlink, Platform, usePlatformStatus } from "./ScoreTooLowBody";
import { Hyperlink, usePlatformStatus } from "./ScoreTooLowBody";
import { Platform } from "../../hooks/useStampPages";
import { ScrollableDiv } from "../ScrollableDiv";
import {
useWidgetIsQuerying,
Expand Down
200 changes: 19 additions & 181 deletions src/components/Body/ScoreTooLowBody.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,22 @@
import { QueryClient } from "@tanstack/react-query";
import styles from "./Body.module.css";
import utilStyles from "../../utilStyles.module.css";
import { Button } from "../Button";
import { useEffect, useMemo, useState } from "react";
import { useHeaderControls } from "../../contexts/HeaderContext";
import { useWidgetPassportScore } from "../../hooks/usePassportScore";
import { usePaginatedStampPages, Platform } from "../../hooks/useStampPages";
import { TextButton } from "../TextButton";
import { displayNumber } from "../../utils";
import { RightArrow } from "../../assets/rightArrow";
import { ScrollableDiv } from "../ScrollableDiv";
import { PlatformVerification } from "./PlatformVerification";

// TODO should probably load this data from an API endpoint, so that
// if we need to add/change/remove stamps, integrators don't need to
// update the package and re-release their apps
// Also at least weights could be scorer-specific
import { useQueryContext } from "../../contexts/QueryContext";

type Credential = {
id: string;
weight: string;
};

export type Platform = {
name: string;
description: JSX.Element;
documentationLink: string;
credentials: Credential[];
displayWeight: string; // calculated
requireSignature?: boolean;
oAuthPopup?: boolean;
};

type StampPage = {
header: string;
platforms: Platform[];
Expand All @@ -56,151 +43,6 @@ export const Hyperlink = ({

const VISIT_PASSPORT_HEADER = "More Options";

const STAMP_PAGES: StampPage[] = [
{
header: "KYC verification",
platforms: [
{
name: "Binance",
description: (
<div>
If you do not have the Binance Account Bound Token (BABT), obtain it{" "}
<a
href="http://google.com"
style={{
color: "inherit",
fontWeight: "700",
textDecoration: "none",
}}
rel="noopener noreferrer"
target="_blank"
>
here
</a>{" "}
 by verifying your identity and logging into your Binance account.
Then return here and click Verify to claim this Stamp.
</div>
),
documentationLink: "https://google.com",
credentials: [
{
// id: "BinanceBABT2",
id: "NFT",
weight: "16",
},
],
},
{
name: "Holonym",
description: <div>TODO</div>,
documentationLink: "https://google.com",
credentials: [
{
id: "HolonymGovIdProvider",
weight: "16",
},
],
},
],
},
{
header: "Biometrics verification",
platforms: [
{
name: "Civic",
description: <div>TODO</div>,
documentationLink: "https://google.com",
credentials: [
{
id: "CivicCaptchaPass",
weight: "1",
},
{
id: "CivicUniquenessPass",
weight: "2",
},
{
id: "CivicLivenessPass",
weight: "3",
},
],
},
],
},
{
header: "Social & Professional Platforms",
platforms: [
{
name: "LinkedIn",
description: <div>Claim Linkedin stamp</div>,
documentationLink: "https://google.com",
requireSignature: true,
oAuthPopup: true,
credentials: [
{
id: "LinkedIn",
weight: "1",
},
],
},
{
name: "Discord",
description: <div>Coming soon</div>,
documentationLink: "https://google.com",
requireSignature: true,
oAuthPopup: true,
credentials: [
{
id: "Discord",
weight: "1",
},
],
},
// {
// name: "Github",
// description: <div>Coming soon</div>,
// documentationLink: "https://google.com",
// requireSignature: true,
// oAuthPopup: true,
// credentials: [
// {
// id: "Github",
// weight: "1",
// },
// ],
// },
{
name: "Google",
description: <div>Coming soon</div>,
documentationLink: "https://google.com",
requireSignature: true,
oAuthPopup: true,
credentials: [
{
id: "Google",
weight: "1",
},
],
},
],
},
{
header: VISIT_PASSPORT_HEADER,
platforms: [],
},
].map((page) => ({
...page,
platforms: page.platforms.map((platform) => ({
...platform,
displayWeight: displayNumber(
platform.credentials.reduce(
(acc, credential) => acc + parseFloat(credential.weight),
0
)
),
})),
}));

export const ScoreTooLowBody = ({
generateSignatureCallback,
}: {
Expand All @@ -215,20 +57,6 @@ export const ScoreTooLowBody = ({
);
};

const usePages = <T,>(pages: T[]) => {
const [idx, setIdx] = useState(0);

const nextPage = () => setIdx((prev) => Math.min(prev + 1, pages.length - 1));
const prevPage = () => setIdx((prev) => Math.max(prev - 1, 0));

const isFirstPage = idx === 0;
const isLastPage = idx === pages.length - 1;

const page = pages[idx];

return { page, nextPage, prevPage, isFirstPage, isLastPage };
};

const ClaimedIcon = () => (
<svg
width="16"
Expand Down Expand Up @@ -300,16 +128,26 @@ const AddStamps = ({
generateSignatureCallback: (message: string) => Promise<string | undefined>;
}) => {
const { setSubtitle } = useHeaderControls();
const { page, nextPage, prevPage, isFirstPage, isLastPage } =
usePages(STAMP_PAGES);

const queryProps = useQueryContext();
const { scorerId, apiKey, queryClient, overrideIamUrl } = queryProps;
const { page, nextPage, prevPage, isFirstPage, isLastPage, loading, error } =
usePaginatedStampPages({
apiKey: apiKey,
scorerId: scorerId,
overrideIamUrl: overrideIamUrl,
queryClient: queryClient,
});
const [openPlatform, setOpenPlatform] = useState<Platform | null>(null);

const { header, platforms } = page;

useEffect(() => {
setSubtitle("VERIFY STAMPS");
});
}, [setSubtitle]);

if (loading) return <div>Loading Stamps Metadata...</div>;
if (error) return <div>{error}</div>;
if (!page) return <div>No stamp metadata available</div>;

const { header, platforms } = page;

if (openPlatform) {
console.log("LARISA HELLO openPlatform", openPlatform);
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/usePassportScore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import axios from "axios";
import { useQueryContext } from "../contexts/QueryContext";
import { useCallback } from "react";

const DEFAULT_IAM_URL = "https://embed.passport.xyz";
export const DEFAULT_IAM_URL = "https://embed.passport.xyz";

export type PassportEmbedProps = {
apiKey: string;
Expand Down
91 changes: 91 additions & 0 deletions src/hooks/useStampPages.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { useEffect, useState } from "react";
import axios from "axios";
import { DEFAULT_IAM_URL } from "./usePassportScore";
import { QueryClient } from "@tanstack/react-query";
export type Credential = {
id: string;
weight: string;
};

export type Platform = {
name: string;
description: string;
documentationLink: string;
credentials: Credential[];
displayWeight: string;
};

export type StampPage = {
header: string;
platforms: Platform[];
};

type StampsMetadataResponse = StampPage[];

export const usePaginatedStampPages = ({
apiKey,
scorerId,
overrideIamUrl,
queryClient,
}: {
apiKey: string;
scorerId: string;
overrideIamUrl?: string;
queryClient?: QueryClient;
}) => {
const [stampPages, setStampPages] = useState<StampPage[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [idx, setIdx] = useState(0);

useEffect(() => {
const fetchStampPages = async () => {
try {
console.log("LARISA DEBUG : fetchStampPages .... ");
// TODO: fix this to use propr url encoding
const response = await axios.get<StampsMetadataResponse>(
`${overrideIamUrl || DEFAULT_IAM_URL}/embed/stamps/metadata?scorerId=${scorerId}`,
{
headers: {
"X-API-KEY": apiKey,
"Content-Type": "application/json",
},
}
);

const data = response.data;

// Convert description from HTML string to JSX
const formattedData = data.map((page: StampPage) => ({
...page,
platforms: page.platforms.map((platform) => ({
...platform,
description: platform.description,
displayWeight: platform.displayWeight,
})),
}));

setStampPages(formattedData);
} catch (err) {
console.error("Error fetching stamp pages:", err);
setError("Failed to load stamp pages");
} finally {
setLoading(false);
}
};

fetchStampPages();
}, []);

// Pagination controls
const nextPage = () =>
setIdx((prev) => Math.min(prev + 1, stampPages.length - 1));
const prevPage = () => setIdx((prev) => Math.max(prev - 1, 0));

const isFirstPage = idx === 0;
const isLastPage = idx === stampPages.length - 1;

const page = stampPages[idx] ?? null;

return { page, nextPage, prevPage, isFirstPage, isLastPage, loading, error };
};

0 comments on commit b7e90b0

Please sign in to comment.