Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
at main 107 lines 2.9 kB view raw
1import { UsersIcon } from "@heroicons/react/24/outline"; 2import { 3 type GroupFragment, 4 type GroupMembersRequest, 5 PageSize, 6 useGroupMembersQuery 7} from "@hey/indexer"; 8import { motion } from "motion/react"; 9import { useCallback } from "react"; 10import { Virtualizer } from "virtua"; 11import SingleAccount from "@/components/Shared/Account/SingleAccount"; 12import AccountListShimmer from "@/components/Shared/Shimmer/AccountListShimmer"; 13import { EmptyState, ErrorMessage } from "@/components/Shared/UI"; 14import cn from "@/helpers/cn"; 15import useLoadMoreOnIntersect from "@/hooks/useLoadMoreOnIntersect"; 16import { useAccountStore } from "@/store/persisted/useAccountStore"; 17import { accountsList } from "@/variants"; 18 19interface MembersProps { 20 group: GroupFragment; 21} 22 23const Members = ({ group }: MembersProps) => { 24 const { currentAccount } = useAccountStore(); 25 26 const request: GroupMembersRequest = { 27 group: group.address, 28 pageSize: PageSize.Fifty 29 }; 30 31 const { data, loading, error, fetchMore } = useGroupMembersQuery({ 32 skip: !group.address, 33 variables: { request } 34 }); 35 36 const groupMembers = data?.groupMembers?.items; 37 const pageInfo = data?.groupMembers?.pageInfo; 38 const hasMore = pageInfo?.next; 39 40 const handleEndReached = useCallback(async () => { 41 if (hasMore) { 42 await fetchMore({ 43 variables: { request: { ...request, cursor: pageInfo?.next } } 44 }); 45 } 46 }, [fetchMore, hasMore, pageInfo?.next, request]); 47 48 const loadMoreRef = useLoadMoreOnIntersect(handleEndReached); 49 50 if (loading) { 51 return <AccountListShimmer />; 52 } 53 54 if (!groupMembers?.length) { 55 return ( 56 <EmptyState 57 hideCard 58 icon={<UsersIcon className="size-8" />} 59 message="Group doesn't have any members." 60 /> 61 ); 62 } 63 64 if (error) { 65 return ( 66 <ErrorMessage 67 className="m-5" 68 error={error} 69 title="Failed to load members" 70 /> 71 ); 72 } 73 74 return ( 75 <div className="max-h-[80vh] overflow-y-auto"> 76 <Virtualizer> 77 {groupMembers.map((member, index) => ( 78 <motion.div 79 animate="visible" 80 className={cn( 81 "divider p-5", 82 index === groupMembers.length - 1 && "border-b-0" 83 )} 84 initial="hidden" 85 key={member.account.address} 86 variants={accountsList} 87 > 88 <SingleAccount 89 account={member.account} 90 hideFollowButton={ 91 currentAccount?.address === member.account.address 92 } 93 hideUnfollowButton={ 94 currentAccount?.address === member.account.address 95 } 96 showBio 97 showUserPreview={false} 98 /> 99 </motion.div> 100 ))} 101 {hasMore && <span ref={loadMoreRef} />} 102 </Virtualizer> 103 </div> 104 ); 105}; 106 107export default Members;