Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
at main 103 lines 2.6 kB view raw
1import type { ApolloCache, NormalizedCacheObject } from "@apollo/client"; 2import { MenuItem } from "@headlessui/react"; 3import { EyeIcon, EyeSlashIcon } from "@heroicons/react/24/outline"; 4import { 5 type PostFragment, 6 type PostNotInterestedRequest, 7 useAddPostNotInterestedMutation, 8 useUndoPostNotInterestedMutation 9} from "@hey/indexer"; 10import type { ApolloClientError } from "@hey/types/errors"; 11import { useCallback } from "react"; 12import { toast } from "sonner"; 13import cn from "@/helpers/cn"; 14import errorToast from "@/helpers/errorToast"; 15import stopEventPropagation from "@/helpers/stopEventPropagation"; 16 17interface NotInterestedProps { 18 post: PostFragment; 19} 20 21const NotInterested = ({ post }: NotInterestedProps) => { 22 const notInterested = post.operations?.isNotInterested; 23 24 const request: PostNotInterestedRequest = { 25 post: post.id 26 }; 27 28 const updateCache = ( 29 cache: ApolloCache<NormalizedCacheObject>, 30 notInterested: boolean 31 ) => { 32 if (!post.operations) { 33 return; 34 } 35 36 cache.modify({ 37 fields: { isNotInterested: () => notInterested }, 38 id: cache.identify(post.operations) 39 }); 40 }; 41 42 const onError = useCallback((error: ApolloClientError) => { 43 errorToast(error); 44 }, []); 45 46 const [addPostNotInterested] = useAddPostNotInterestedMutation({ 47 onCompleted: () => { 48 toast.success("Marked as not Interested"); 49 }, 50 onError, 51 update: (cache) => updateCache(cache, true), 52 variables: { request } 53 }); 54 55 const [undoPostNotInterested] = useUndoPostNotInterestedMutation({ 56 onCompleted: () => { 57 toast.success("Undo Not interested"); 58 }, 59 onError, 60 update: (cache) => updateCache(cache, false), 61 variables: { request } 62 }); 63 64 const handleToggleNotInterested = async () => { 65 if (notInterested) { 66 return await undoPostNotInterested(); 67 } 68 69 return await addPostNotInterested(); 70 }; 71 72 return ( 73 <MenuItem 74 as="div" 75 className={({ focus }) => 76 cn( 77 { "dropdown-active": focus }, 78 "m-2 block cursor-pointer rounded-lg px-2 py-1.5 text-sm" 79 ) 80 } 81 onClick={(event) => { 82 stopEventPropagation(event); 83 handleToggleNotInterested(); 84 }} 85 > 86 <div className="flex items-center space-x-2"> 87 {notInterested ? ( 88 <> 89 <EyeIcon className="size-4" /> 90 <div>Undo Not interested</div> 91 </> 92 ) : ( 93 <> 94 <EyeSlashIcon className="size-4" /> 95 <div>Not interested</div> 96 </> 97 )} 98 </div> 99 </MenuItem> 100 ); 101}; 102 103export default NotInterested;