Skip to content
Merged
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
48 changes: 46 additions & 2 deletions apps/storybook/src/hooks/use-efp-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,32 @@ export type EfpRecord = {
record_type: 'address'
}

export type EfpEnsData = {
name: string,
address: Address,
avatar: string,
records: {
avatar?: string,
"com.discord"?: string,
"com.github"?: string,
"com.twitter"?: string,
description?: string,
email?: string,
header?: string,
location?: string,
name?: string,
"org.telegram"?: string,
url?: string,
[key: string]: string | undefined
},
updated_at: string
}

export type EfpUserStats = {
followers_count: string,
following_count: string,
}

export type EfpApiOptions = {
limit?:number, sort?:any
}
Expand All @@ -42,6 +68,10 @@ export const getEndpointEnsData = (addressOrEns:AddressOrEns, options?:EfpApiOpt
return `${EFP_ENDPOINT}users/${addressOrEns}/ens?${qs.stringify({limit, sort})}`
}

export const getEndpointUserStats = (addressOrEns:AddressOrEns)=>{
return `${EFP_ENDPOINT}users/${addressOrEns}/stats`
}




Expand Down Expand Up @@ -73,7 +103,7 @@ export const useFollowing = (addressOrEns:AddressOrEns) =>{
}

export const useEnsData = (addressOrEns:AddressOrEns) =>{
return useQuery({
return useQuery<{ens: EfpEnsData}>({
queryKey: ['ethfollow.ens', addressOrEns],
queryFn: async () =>{

Expand All @@ -84,4 +114,18 @@ export const useEnsData = (addressOrEns:AddressOrEns) =>{
}

});
}
}

export const useUserStats = (addressOrEns:AddressOrEns) =>{
return useQuery<EfpUserStats>({
queryKey: ['ethfollow.user-stats', addressOrEns],
queryFn: async () =>{


const endpoint = getEndpointUserStats(addressOrEns);

return fetch(endpoint).then(res=>res.json());
}

});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Meta, StoryObj } from '@storybook/react';

import { NameAndFollowerCountBadge } from './NameAndFollowerCountBadge';
import { BY_USER } from '../fixture';
import { withQueryClientProvider } from '../decorators/wagmi';


const meta = {
title: 'SocialGraph/NameAndFollowerCountBadge',
component: NameAndFollowerCountBadge,
parameters: {
layout: 'centered',
},
args: {},
} satisfies Meta<typeof NameAndFollowerCountBadge>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Address: Story = {
args: {
addressOrEns: BY_USER.vitalik.address
},
decorators: [
withQueryClientProvider()
]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { AddressOrEns, useEnsData, useUserStats } from "@/hooks/use-efp-api";
import { Text } from "@radix-ui/themes";
import { Card, CardContent } from "@/components/ui/card"

import { useEffect, useState } from "react";

export type NameWithEfpFollowerCount = { name: string, followers: number };

export const NameAndFollowerCountBadge = ({ addressOrEns }: { addressOrEns: AddressOrEns }) => {
const [nameWithFollowerCount, setNameWithFollowerCount] = useState<NameWithEfpFollowerCount>();

const ensQuery = useEnsData(addressOrEns);
const userStatsQuery = useUserStats(addressOrEns);

// consider extracted as common hook but ensure treeshaking
useEffect(() => {
if (!ensQuery.isSuccess || !userStatsQuery.isSuccess) return;
; (async () => {
const name = ensQuery.data.ens.records.name ?? ensQuery.data.ens.name;
const followers = parseInt(userStatsQuery.data.followers_count);

setNameWithFollowerCount({ name, followers });
})();
}, [ensQuery.isSuccess, userStatsQuery.isSuccess]);

return (
<Card className="w-32 h-16">
<CardContent className="p-2">
<Text as="div" size="2" weight="bold">
{ nameWithFollowerCount?.name }
</Text>
<Text as="div" size="2" color="gray">
{ nameWithFollowerCount?.followers ? `${nameWithFollowerCount.followers} followers` : '' }
</Text>
</CardContent>
</Card>
)
}