Skip to content

Commit

Permalink
feat: stamp filtering (passportxyz#766)
Browse files Browse the repository at this point in the history
* add stamp filtering via GET parameter

* get query string via nextjs router hook

* update getStampProviderFilters function

* hide hide stamps in StampSelector

* add STAMP_FILTERS + getFilterName

* improve getStampProviderFilters

* display filterName + add link to remove

* fix(app): mock next router and lint

---------

Co-authored-by: schultztimothy <[email protected]>
  • Loading branch information
didierkrux and tim-schultz authored Feb 27, 2023
1 parent f62e349 commit 9301788
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 1 deletion.
6 changes: 6 additions & 0 deletions app/__tests__/components/AdditionalStampModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ jest.mock("@didtools/cacao", () => ({
},
}));

jest.mock("next/router", () => ({
useRouter: () => ({
query: { filter: "" },
}),
}));

const mockPossibleEVMStamps = [
{
validatedPlatformGroups: [
Expand Down
6 changes: 6 additions & 0 deletions app/__tests__/components/CardList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ jest.mock("@didtools/cacao", () => ({
},
}));

jest.mock("next/router", () => ({
useRouter: () => ({
query: { filter: "" },
}),
}));

const mockUserContext: UserContextState = makeTestUserContext();
const mockCeramicContext: CeramicContextState = makeTestCeramicContext();

Expand Down
6 changes: 6 additions & 0 deletions app/__tests__/components/GenericPlatform.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ jest.mock("../../utils/helpers.tsx", () => ({
}),
}));

jest.mock("next/router", () => ({
useRouter: () => ({
query: { filter: "" },
}),
}));

const mockToggleConnection = jest.fn();
const mockCreatePassport = jest.fn();
const mockHandleAddStamp = jest.fn().mockResolvedValue(undefined);
Expand Down
6 changes: 6 additions & 0 deletions app/__tests__/components/SideBarContent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ import { PROVIDER_ID } from "@gitcoin/passport-types";

jest.mock("../../utils/onboard.ts");

jest.mock("next/router", () => ({
useRouter: () => ({
query: { filter: "" },
}),
}));

const verifiedProviders: PROVIDER_ID[] = ["Github", "FiveOrMoreGithubRepos", "ForkedGithubRepoProvider"];
const selectedProviders: PROVIDER_ID[] = ["Github", "FiveOrMoreGithubRepos", "ForkedGithubRepoProvider"];

Expand Down
6 changes: 6 additions & 0 deletions app/__tests__/pages/Dashboard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ jest.mock("@didtools/cacao", () => ({
},
}));

jest.mock("next/router", () => ({
useRouter: () => ({
query: { filter: "" },
}),
}));

const mockToggleConnection = jest.fn();
const mockHandleDisconnection = jest.fn();
const mockSigner = mock(JsonRpcSigner) as unknown as JsonRpcSigner;
Expand Down
11 changes: 11 additions & 0 deletions app/components/PlatformCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// --- React Methods
import { useContext, useEffect } from "react";
import { useRouter } from "next/router";

// --- Chakra UI Elements
import { useDisclosure, Menu, MenuButton, MenuList, MenuItem } from "@chakra-ui/react";
Expand All @@ -16,6 +17,7 @@ import { pillLocalStorage } from "../context/userContext";
// --- Components
import { JsonOutputModal } from "./JsonOutputModal";
import { RemoveStampModal } from "./RemoveStampModal";
import { getStampProviderFilters } from "../config/filters";

type SelectedProviders = Record<PLATFORM_ID, PROVIDER_ID[]>;

Expand Down Expand Up @@ -43,6 +45,10 @@ export const PlatformCard = ({
// import all providers
const { allProvidersState, passportHasCacaoError, handleDeleteStamps } = useContext(CeramicContext);

// stamp filter
const router = useRouter();
const { filter } = router.query;

// useDisclosure to control JSON modal
const {
isOpen: isOpenJsonOutputModal,
Expand All @@ -59,6 +65,11 @@ export const PlatformCard = ({

const disabled = passportHasCacaoError();

// hide platforms based on filter
const stampFilters = filter?.length && typeof filter === "string" ? getStampProviderFilters(filter) : false;
const hidePlatform = stampFilters && !Object.keys(stampFilters).includes(platform.platform);
if (hidePlatform) return <></>;

// returns a single Platform card
return (
<div className="w-1/2 p-2 md:w-1/2 xl:w-1/4" key={`${platform.name}${i}`}>
Expand Down
1 change: 1 addition & 0 deletions app/components/SideBarContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export const SideBarContent = ({
</div>
<hr className="border-1" />
<StampSelector
currentPlatform={currentPlatform}
currentProviders={currentProviders}
verifiedProviders={verifiedProviders}
selectedProviders={selectedProviders}
Expand Down
15 changes: 15 additions & 0 deletions app/components/StampSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
import { useRouter } from "next/router";
import { Switch } from "@chakra-ui/react";
import { PROVIDER_ID } from "@gitcoin/passport-types";
import { PlatformSpec } from "@gitcoin/passport-platforms/dist/commonjs/types";
import { useState } from "react";
import { PlatformGroupSpec } from "../config/providers";
import { getStampProviderFilters } from "../config/filters";

type StampSelectorProps = {
currentPlatform?: PlatformSpec | undefined;
currentProviders: PlatformGroupSpec[] | undefined;
verifiedProviders: PROVIDER_ID[] | undefined;
selectedProviders: PROVIDER_ID[] | undefined;
setSelectedProviders: (providerIds: PROVIDER_ID[]) => void;
};

export function StampSelector({
currentPlatform,
currentProviders,
verifiedProviders,
selectedProviders,
setSelectedProviders,
}: StampSelectorProps) {
// stamp filter
const router = useRouter();
const { filter } = router.query;
const stampFilters = filter?.length && typeof filter === "string" ? getStampProviderFilters(filter) : false;

return (
<>
{/* each of the available providers in this platform */}
{currentProviders?.map((stamp, i) => {
// hide stamps based on filter
const hideStamp =
stampFilters && currentPlatform && !stampFilters[currentPlatform?.platform]?.includes(stamp.platformGroup);
if (hideStamp) return null;

return (
<div key={i} className="border-b py-4 px-6">
<p className="ml-4 text-sm font-bold">{stamp.platformGroup}</p>
Expand Down
38 changes: 38 additions & 0 deletions app/config/filters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export const STAMP_FILTERS: {
[key: string]: {
name: string;
stamps: {
[key: string]: string[];
};
};
} = {
"bankless-academy": {
name: "Bankless Academy",
stamps: {
Google: ["Account Name"],
Ens: ["Account Name"],
Poh: ["Account Name"],
Twitter: ["Account Name"],
Facebook: ["Account Name"],
Brightid: ["Account Name"],
Linkedin: ["Account Name"],
Discord: ["Account Name"],
},
},
};

export const getStampProviderFilters = (filter: string): any => {
let stampFilters: any = false;
if (Object.keys(STAMP_FILTERS).includes(filter)) {
stampFilters = STAMP_FILTERS[filter].stamps;
}
return stampFilters;
};

export const getFilterName = (filter: string): any => {
let filterName: any = false;
if (Object.keys(STAMP_FILTERS).includes(filter)) {
filterName = STAMP_FILTERS[filter].name;
}
return filterName;
};
18 changes: 17 additions & 1 deletion app/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// --- React Methods
import React, { useContext, useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { useRouter } from "next/router";

// --Components
import { CardList } from "../components/CardList";
Expand Down Expand Up @@ -29,6 +30,7 @@ import { Banner } from "../components/Banner";
import { RefreshStampModal } from "../components/RefreshStampModal";
import { ExpiredStampModal } from "../components/ExpiredStampModal";
import ProcessingPopup from "../components/ProcessingPopup";
import { getFilterName } from "../config/filters";

export default function Dashboard() {
const { passport, isLoadingPassport, passportHasCacaoError, cancelCeramicConnection, expiredProviders } =
Expand All @@ -45,6 +47,11 @@ export default function Dashboard() {
const [refreshModal, setRefreshModal] = useState(false);
const [expiredStampModal, setExpiredStampModal] = useState(false);

// stamp filter
const router = useRouter();
const { filter } = router.query;
const filterName = filter?.length && typeof filter === "string" ? getFilterName(filter) : false;

// Route user to home when wallet is disconnected
useEffect(() => {
if (!wallet) {
Expand Down Expand Up @@ -165,7 +172,16 @@ export default function Dashboard() {

<div className="container mx-auto flex flex-wrap-reverse px-2 md:mt-4 md:flex-wrap">
<div className="md:w-3/5">
<p className="mb-4 text-2xl text-black">My Stamps</p>
<p className="mb-4 text-2xl text-black">
My {filterName && `${filterName} `}Stamps
{filterName && (
<a href="/#/dashboard">
<span data-testid="select-all" className={`pl-2 text-sm text-purple-connectPurple`}>
see all my stamps
</span>
</a>
)}
</p>
<p className="text-xl text-black">
Gitcoin Passport is an identity aggregator that helps you build a digital identifier showcasing your unique
humanity. Select the verification stamps you&apos;d like to connect to start building your passport. The
Expand Down

0 comments on commit 9301788

Please sign in to comment.