Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: consolidated URL overrides, added linting and fixed issues #15

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": ["warn"],
},
}
);
10 changes: 4 additions & 6 deletions example/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ import { useState } from "react";
const passportEmbedParams = {
apiKey: import.meta.env.VITE_API_KEY,
scorerId: import.meta.env.VITE_SCORER_ID,
// overrideIamUrl: "https://embed.review.passport.xyz",
overrideIamUrl: "http://localhost:8004",
// challengeSignatureUrl: "https://iam.review.passport.xyz/api/v0.0.0/challenge",
challengeSignatureUrl: "http://localhost:8004/embed/challenge",
overrideEmbedServiceUrl: "http://localhost:8004",
};

const connectWallet = async () => {
Expand Down Expand Up @@ -70,6 +67,7 @@ const generateSignature = async (message: string) => {
const DirectPassportDataAccess = ({ address }: { address?: string }) => {
const { data, isError, error } = usePassportScore({
...passportEmbedParams,
embedServiceUrl: passportEmbedParams.overrideEmbedServiceUrl,
address,
});

Expand All @@ -84,7 +82,7 @@ const DirectPassportDataAccess = ({ address }: { address?: string }) => {
What stamps?
<pre>{JSON.stringify(data?.stamps, undefined, 2)}</pre>
</li>
{isError && <li>Error: {error?.message}</li>}
{isError && <li>Error: {(error as Error)?.message}</li>}
</ul>
</div>
);
Expand Down Expand Up @@ -133,7 +131,7 @@ const Dashboard = () => {
);
};

const App = () => <Dashboard />;
export const App = () => <Dashboard />;

const rootElement = document.getElementById("root");
if (rootElement) {
Expand Down
13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@
"build:types": "tsc --declaration --declarationDir dist --emitDeclarationOnly",
"dev": "cd example && yarn dev",
"watch:css": "postcss 'src/**/*.css' -d dist/esm/ --base src --watch",
"watch:esm": "tsc --module ESNext --outDir dist/esm --watch"
"watch:esm": "tsc --module ESNext --outDir dist/esm --watch",
"lint": "eslint ."
},
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
"react": ">=18.0.0",
"react-dom": ">=18.0.0"
},
"devDependencies": {
"@babel/core": "^7.26.7",
Expand All @@ -53,6 +54,7 @@
"@babel/preset-typescript": "^7.26.0",
"@babel/runtime": "^7.26.7",
"@babel/runtime-corejs3": "^7.26.7",
"@eslint/js": "^9.19.0",
"@jest/globals": "^29.7.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
Expand All @@ -64,6 +66,10 @@
"babel-loader": "^9.2.1",
"core-js": "3",
"css-loader": "^7.1.2",
"eslint": "^9.19.0",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.18",
"globals": "^15.14.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
Expand All @@ -77,6 +83,7 @@
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"typescript": "^5.6.3",
"typescript-eslint": "^8.23.0",
"webpack": "^5.97.1",
"webpack-cli": "^6.0.1"
},
Expand Down
6 changes: 4 additions & 2 deletions src/components/Body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ const BodyRouter = ({
if (isError) {
let errorMessage = "An error occurred";
try {
errorMessage = error.message;
} catch {}
errorMessage = (error as Error).message;
} catch {
/* ignore if error is unexpected format */
}
return <ErrorBody errorMessage={errorMessage} />;
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/Body/CheckingBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import styles from "./Body.module.css";
import utilStyles from "../../utilStyles.module.css";
import { Button } from "../Button";
import { useEffect } from "react";
import { useHeaderControls } from "../../contexts/HeaderContext";
import { useHeaderControls } from "../../hooks/useHeaderControls";

export const CheckingBody = () => {
const { setSubtitle } = useHeaderControls();
Expand Down
2 changes: 1 addition & 1 deletion src/components/Body/CongratsBody.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect } from "react";
import { useHeaderControls } from "../../contexts/HeaderContext";
import { useHeaderControls } from "../../hooks/useHeaderControls";
import styles from "./Body.module.css";

export const CongratsBody = () => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Body/ConnectWalletBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import utilStyles from "../../utilStyles.module.css";
import { Button } from "../Button";
import { useEffect, useState } from "react";
import { PassportEmbedProps } from "../../hooks/usePassportScore";
import { useHeaderControls } from "../../contexts/HeaderContext";
import { useHeaderControls } from "../../hooks/useHeaderControls";

// TODO technically this might not have a threshold of 20, but
// how would we know at this point before we've made a request
Expand Down
2 changes: 1 addition & 1 deletion src/components/Body/ErrorBody.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect } from "react";
import styles from "./Body.module.css";
import utilStyles from "../../utilStyles.module.css";
import { useHeaderControls } from "../../contexts/HeaderContext";
import { useHeaderControls } from "../../hooks/useHeaderControls";
import { Button } from "../Button";
import { useResetWidgetPassportScore } from "../../hooks/usePassportScore";

Expand Down
58 changes: 25 additions & 33 deletions src/components/Body/PlatformVerification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@ import {
useWidgetIsQuerying,
useWidgetVerifyCredentials,
} from "../../hooks/usePassportScore";
import { useQueryContext } from "../../contexts/QueryContext";
import { useQueryContext } from "../../hooks/useQueryContext";
import { usePlatformStatus } from "../../hooks/usePlatformStatus";
import { Platform } from "../../hooks/useStampPages";

const DEFAULT_CHALLENGE_URL =
"https://iam.review.passport.xyz/api/v0.0.0/challenge";

const CloseIcon = () => (
<svg
width="12"
Expand All @@ -41,6 +38,28 @@ const CloseIcon = () => (
</svg>
);

const getChallenge = async (
challengeUrl: string,
address: string,
providerType: string
) => {
const payload = {
address: address,
signatureType: "EIP712",
type: providerType,
};

const response = await fetch(challengeUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ payload }),
});

return response.json();
};

export const PlatformVerification = ({
platform,
onClose,
Expand Down Expand Up @@ -69,28 +88,6 @@ export const PlatformVerification = ({
}
}, [initiatedVerification, isQuerying, claimed, onClose]);

const getChallenge = async (
challengeUrl: string,
address: string,
providerType: string
) => {
const payload = {
address: address,
signatureType: "EIP712",
type: providerType,
};

const response = await fetch(challengeUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ payload }),
});

return response.json();
};

return (
<div className={styles.container}>
<div className={styles.headerContainer}>
Expand Down Expand Up @@ -138,10 +135,7 @@ export const PlatformVerification = ({
return;
}

// TODO: fix this URL
const challengeEndpoint = `${
queryProps.challengeSignatureUrl || DEFAULT_CHALLENGE_URL
}`;
const challengeEndpoint = `${queryProps.embedServiceUrl}/embed/challenge`;
const challenge = await getChallenge(
challengeEndpoint,
queryProps.address,
Expand Down Expand Up @@ -190,9 +184,7 @@ export const PlatformVerification = ({
if (popup.closed) {
clearInterval(checkPopupClosed);
console.log("Pop-up closed");
alert(
"LinkedIn OAuth process completed or cancelled. Interval check"
);
alert("OAuth process completed or cancelled. Interval check");
// Refresh stamps
verifyCredentials(platformCredentialIds);
}
Expand Down
8 changes: 4 additions & 4 deletions src/components/Body/ScoreTooLowBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import styles from "./Body.module.css";
import utilStyles from "../../utilStyles.module.css";
import { Button } from "../Button";
import { useEffect, useState } from "react";
import { useHeaderControls } from "../../contexts/HeaderContext";
import { useHeaderControls } from "../../hooks/useHeaderControls";
import { useWidgetPassportScore } from "../../hooks/usePassportScore";
import { usePaginatedStampPages, Platform } from "../../hooks/useStampPages";
import { TextButton } from "../TextButton";
import { RightArrow } from "../../assets/rightArrow";
import { ScrollableDiv } from "../ScrollableDiv";
import { PlatformVerification } from "./PlatformVerification";
import { useQueryContext } from "../../contexts/QueryContext";
import { useQueryContext } from "../../hooks/useQueryContext";
import { usePlatformStatus } from "../../hooks/usePlatformStatus";

export const Hyperlink = ({
Expand Down Expand Up @@ -99,12 +99,12 @@ export const AddStamps = ({
}) => {
const { setSubtitle } = useHeaderControls();
const queryProps = useQueryContext();
const { scorerId, apiKey, overrideIamUrl } = queryProps;
const { scorerId, apiKey, embedServiceUrl } = queryProps;
const { page, nextPage, prevPage, isFirstPage, isLastPage, loading, error } =
usePaginatedStampPages({
apiKey,
scorerId,
overrideIamUrl,
embedServiceUrl,
});
const [openPlatform, setOpenPlatform] = useState<Platform | null>(null);

Expand Down
2 changes: 1 addition & 1 deletion src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { PassportLogo } from "../assets/passportLogo";
import { CheckmarkIcon } from "../assets/checkmarkIcon";
import { XIcon } from "../assets/xIcon";
import { Ellipsis } from "./Ellipsis";
import { useHeaderControls } from "../contexts/HeaderContext";
import { useHeaderControls } from "../hooks/useHeaderControls";
import {
useWidgetIsQuerying,
useWidgetPassportScore,
Expand Down
22 changes: 22 additions & 0 deletions src/components/HeaderContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useMemo, useState } from "react";
import { HeaderContext } from "../contexts/HeaderContext";

export const HeaderContextProvider = ({
children,
}: {
children: React.ReactNode;
}) => {
const [subtitle, setSubtitle] = useState("");

const value = useMemo(
() => ({
subtitle,
setSubtitle,
}),
[subtitle]
);

return (
<HeaderContext.Provider value={value}>{children}</HeaderContext.Provider>
);
};
32 changes: 32 additions & 0 deletions src/components/QueryContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useMemo } from "react";
import {
QueryContext,
DEFAULT_EMBED_SERVICE_URL,
} from "../contexts/QueryContext";
import { PassportEmbedProps } from "../hooks/usePassportScore";

export const QueryContextProvider = ({
children,
apiKey,
address,
scorerId,
overrideEmbedServiceUrl,
}: {
children: React.ReactNode;
} & PassportEmbedProps) => {
const value = useMemo(
() => ({
apiKey,
address,
scorerId,
embedServiceUrl:
overrideEmbedServiceUrl?.replace(/\/*$/, "") ||
DEFAULT_EMBED_SERVICE_URL,
}),
[apiKey, address, scorerId, overrideEmbedServiceUrl]
);

return (
<QueryContext.Provider value={value}>{children}</QueryContext.Provider>
);
};
8 changes: 5 additions & 3 deletions src/components/ScrollableDiv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,15 @@ const ScrollIndicator = ({
});

// Initial visibility check on mount
scrollContainerRef.current && onScroll(scrollContainerRef.current);
if (scrollContainerRef.current) onScroll(scrollContainerRef.current);

const localRef = scrollContainerRef.current;

// Remove on dismount
return () => {
scrollContainerRef.current?.removeEventListener("scroll", onScrollEvent);
localRef?.removeEventListener("scroll", onScrollEvent);
};
}, [scrollContainerRef]);
}, [scrollContainerRef, direction]);

return (
<div
Expand Down
Loading