Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
26 changes: 26 additions & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@talentlayer/react",
"version": "0.0.1",
"description": "The TalentLayer Client for React with abstractions for easy interaction with the TalentLayer protocol",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",
Comment thread
marsian83 marked this conversation as resolved.
Outdated
"private": false,
"scripts": {
"lint": "eslint .",
"prepare": "npm run build",
"build": "tsc"
},
"devDependencies": {
"@turbo/gen": "^1.10.12",
"@types/node": "^20.6.0",
"eslint-config-custom": "*",
"tsconfig": "*",
"typescript": "^5.2.2"
},
"dependencies": {
"axios": "^1.5.0",
"react": "^18.2.0",
"wagmi": "^1.4.2"
}
}
120 changes: 120 additions & 0 deletions packages/react/src/contexts/talentLayerContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React from "react";
import { createContext, ReactNode, useEffect, useMemo, useState } from "react";
import { useAccount } from "wagmi";
import { IAccount, ICompletionScores, IUser } from "../types";
import { getPlatform } from "../temp";
import { getCompletionScores } from "../utils/profile";
import { TalentLayerClient } from "../../../client/src/index";
import { TalentLayerClientConfig } from "../../../client/src/types";

interface TalentLayerProviderProps {
children: ReactNode;
config: TalentLayerClientConfig & {
platformId: string;
isActiveDelegate?: boolean;
delegateAddress?: string;
};
}

const TalentLayerContext = createContext<{
user?: IUser;
account?: IAccount;
isActiveDelegate: boolean;
refreshData: () => Promise<boolean>;
loading: boolean;
completionScores?: ICompletionScores;
}>({
user: undefined,
account: undefined,
isActiveDelegate: false,
refreshData: async () => {
return false;
},
loading: true,
completionScores: undefined,
});

export function TalentLayerProvider(props: TalentLayerProviderProps) {
const { children, config } = props;

const account = useAccount();

const [user, setUser] = useState<IUser | undefined>();
const [isActiveDelegate, setIsActiveDelegate] = useState(false);
const [loading, setLoading] = useState(true);
const [completionScores, setCompletionScores] = useState<ICompletionScores>();

const tlClient = new TalentLayerClient(config);
Comment thread
marsian83 marked this conversation as resolved.
Outdated

// TODO - automatically switch to the default chain is the current one is not part of the config
Comment thread
marsian83 marked this conversation as resolved.
Outdated

async function fetchData() {
if (!account.address || !account.isConnected) {
setLoading(false);
return false;
}

try {
const userResponse = await tlClient.profile.getByAddress(account.address);

if (userResponse?.data?.data?.users?.length == 0) {
setLoading(false);
return false;
}

const currentUser = userResponse.data.data.users[0];

const platformResponse = await getPlatform(tlClient, config.platformId);

const platform = platformResponse?.data?.data?.platform;
currentUser.isAdmin = platform?.address === currentUser?.address;

setUser(currentUser);
setIsActiveDelegate(
config.isActiveDelegate &&
config.delegateAddress &&
userResponse.data.data.users[0].delegates &&
userResponse.data.data.users[0].delegates.indexOf(
config.delegateAddress.toLowerCase()
) !== -1
);

setLoading(false);
return true;
} catch (err: any) {
setLoading(false);
console.error(err);
//TODO - Handle error for the developer in a visual manner
Comment thread
marsian83 marked this conversation as resolved.
Outdated
return false;
}
}

useEffect(() => {
fetchData();
}, [account.address]);

useEffect(() => {
if (!user) return;
const completionScores = getCompletionScores(user);
setCompletionScores(completionScores);
}, [user]);

const value = useMemo(() => {
return {
user,
account: account ? account : undefined,
isActiveDelegate,
refreshData: fetchData,
loading,
completionScores,
};
}, [account.address, user?.id, isActiveDelegate, loading, completionScores]);

return (
<TalentLayerContext.Provider value={value}>
{children}
</TalentLayerContext.Provider>
);
}

export default TalentLayerContext;
6 changes: 6 additions & 0 deletions packages/react/src/hooks/useTalentLayer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { useContext } from "react";
import TalentLayerContext from "../contexts/talentLayerContext";

export default function useTalentLayer() {
return useContext(TalentLayerContext);
}
8 changes: 8 additions & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import TalentLayerContext from "./contexts/talentLayerContext";
import { TalentLayerProvider } from "./contexts/talentLayerContext";
import useTalentLayer from "./hooks/useTalentLayer";

export default {
context: { TalentLayerContext, TalentLayerProvider },
hooks: { useTalentLayer },
};
48 changes: 48 additions & 0 deletions packages/react/src/temp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { TalentLayerClient } from "../../client/src";

const platformFields = `
id
address
name
createdAt
updatedAt
feePayments
totalPlatformGains
feeClaims
originServiceFeeRate
originValidatedProposalFeeRate
servicePostingFee
proposalPostingFee
arbitrator
arbitratorExtraData
arbitrationFeeTimeout
cid
description
signer
`;

const platformDescriptionFields = `
id
about
website
platform
video_url
image_url
`;

export function getPlatform(
tlClient: TalentLayerClient,
id: string
): Promise<any> {
const query = `
{
platform(id: ${id}) {
${platformFields}
description {
${platformDescriptionFields}
}
}
}
`;
return tlClient.graphQlClient.getFromSubgraph(query);
}
Loading