Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
at main 135 lines 3.9 kB view raw
1import { AtSymbolIcon } from "@heroicons/react/24/outline"; 2import { 3 useAssignUsernameToAccountMutation, 4 useUsernamesQuery 5} from "@hey/indexer"; 6import type { ApolloClientError } from "@hey/types/errors"; 7import { useCallback, useState } from "react"; 8import { toast } from "sonner"; 9import LazySmallSingleAccount from "@/components/Shared/Account/LazySmallSingleAccount"; 10import Loader from "@/components/Shared/Loader"; 11import Slug from "@/components/Shared/Slug"; 12import { Button, EmptyState, H6 } from "@/components/Shared/UI"; 13import errorToast from "@/helpers/errorToast"; 14import useTransactionLifecycle from "@/hooks/useTransactionLifecycle"; 15import { useAccountStore } from "@/store/persisted/useAccountStore"; 16 17const LinkUsername = () => { 18 const { currentAccount } = useAccountStore(); 19 const [linkingUsername, setLinkingUsername] = useState<null | string>(null); 20 const handleTransactionLifecycle = useTransactionLifecycle(); 21 22 const onCompleted = () => { 23 setLinkingUsername(null); 24 toast.success("Linked"); 25 }; 26 27 const onError = useCallback((error: ApolloClientError) => { 28 setLinkingUsername(null); 29 errorToast(error); 30 }, []); 31 32 const { data, loading } = useUsernamesQuery({ 33 variables: { 34 request: { 35 filter: { 36 namespace: "0x1aA55B9042f08f45825dC4b651B64c9F98Af4615", 37 owner: currentAccount?.address 38 } 39 } 40 } 41 }); 42 43 const [assignUsernameToAccount] = useAssignUsernameToAccountMutation({ 44 onCompleted: async ({ assignUsernameToAccount }) => { 45 if (assignUsernameToAccount.__typename === "AssignUsernameResponse") { 46 return onCompleted(); 47 } 48 49 return await handleTransactionLifecycle({ 50 onCompleted, 51 onError, 52 transactionData: assignUsernameToAccount 53 }); 54 }, 55 onError 56 }); 57 58 const handleLink = async (localName: string) => { 59 if (!currentAccount) { 60 return; 61 } 62 63 const confirmation = confirm( 64 "Are you sure you want to link this username to your account?" 65 ); 66 67 if (!confirmation) { 68 return; 69 } 70 71 setLinkingUsername(localName); 72 73 return await assignUsernameToAccount({ 74 variables: { request: { username: { localName } } } 75 }); 76 }; 77 78 if (loading) { 79 return <Loader className="my-10" />; 80 } 81 82 const usernames = data?.usernames.items; 83 84 if (!usernames?.length) { 85 return ( 86 <EmptyState 87 hideCard 88 icon={<AtSymbolIcon className="size-8" />} 89 message="No usernames found to link!" 90 /> 91 ); 92 } 93 94 return ( 95 <div className="m-5 flex flex-col gap-y-5"> 96 <div className="flex flex-col gap-y-1.5"> 97 <b>Link a username</b> 98 <H6 className="font-normal text-gray-500 dark:text-gray-200"> 99 Link a username to your account to showcase it publicly, allowing 100 others to easily identify and connect with you based on your unique 101 online identity. 102 </H6> 103 </div> 104 {usernames?.map((username) => ( 105 <div 106 className="flex flex-wrap items-center justify-between gap-3" 107 key={username.value} 108 > 109 <div className="flex items-center space-x-2"> 110 <Slug className="font-bold" slug={username.value} /> 111 {username.linkedTo ? ( 112 <div className="flex items-center space-x-2"> 113 <span></span> 114 <div>Linked to</div> 115 <LazySmallSingleAccount address={username.linkedTo} /> 116 </div> 117 ) : null} 118 </div> 119 {username.linkedTo ? null : ( 120 <Button 121 disabled={linkingUsername === username.localName} 122 loading={linkingUsername === username.localName} 123 onClick={() => handleLink(username.localName)} 124 outline 125 > 126 Link 127 </Button> 128 )} 129 </div> 130 ))} 131 </div> 132 ); 133}; 134 135export default LinkUsername;