Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
1import { useApolloClient } from "@apollo/client";
2import {
3 type GroupFragment,
4 useJoinGroupMutation,
5 useRequestGroupMembershipMutation
6} from "@hey/indexer";
7import type { ApolloClientError } from "@hey/types/errors";
8import { useCallback, useState } from "react";
9import { toast } from "sonner";
10import { Button } from "@/components/Shared/UI";
11import errorToast from "@/helpers/errorToast";
12import useTransactionLifecycle from "@/hooks/useTransactionLifecycle";
13
14interface JoinProps {
15 group: GroupFragment;
16 small: boolean;
17 className?: string;
18 title?: string;
19 onSuccess?: () => void;
20}
21
22const Join = ({
23 group,
24 small,
25 className = "",
26 title = "Join",
27 onSuccess
28}: JoinProps) => {
29 const [isSubmitting, setIsSubmitting] = useState(false);
30 const { cache } = useApolloClient();
31 const handleTransactionLifecycle = useTransactionLifecycle();
32 const updateCache = () => {
33 if (!group.operations) {
34 return;
35 }
36
37 cache.modify({
38 fields: {
39 hasRequestedMembership: () => group.membershipApprovalEnabled,
40 isMember: () => !group.membershipApprovalEnabled
41 },
42 id: cache.identify(group.operations)
43 });
44 };
45
46 const onCompleted = () => {
47 updateCache();
48 setIsSubmitting(false);
49 onSuccess?.();
50 toast.success(
51 group.membershipApprovalEnabled ? "Request sent" : "Joined group"
52 );
53 };
54
55 const onError = useCallback((error: ApolloClientError) => {
56 setIsSubmitting(false);
57 errorToast(error);
58 }, []);
59
60 const [joinGroup] = useJoinGroupMutation({
61 onCompleted: async ({ joinGroup }) => {
62 if (joinGroup.__typename === "JoinGroupResponse") {
63 return onCompleted();
64 }
65
66 if (joinGroup.__typename === "GroupOperationValidationFailed") {
67 return onError({ message: joinGroup.reason });
68 }
69
70 return await handleTransactionLifecycle({
71 onCompleted,
72 onError,
73 transactionData: joinGroup
74 });
75 },
76 onError
77 });
78
79 const [requestGroupMembership] = useRequestGroupMembershipMutation({
80 onCompleted: async ({ requestGroupMembership }) => {
81 if (
82 requestGroupMembership.__typename === "RequestGroupMembershipResponse"
83 ) {
84 return onCompleted();
85 }
86
87 return await handleTransactionLifecycle({
88 onCompleted,
89 onError,
90 transactionData: joinGroup
91 });
92 },
93 onError
94 });
95
96 const handleJoin = async () => {
97 setIsSubmitting(true);
98
99 if (group.membershipApprovalEnabled) {
100 return await requestGroupMembership({
101 variables: { request: { group: group.address } }
102 });
103 }
104
105 return await joinGroup({
106 variables: { request: { group: group.address } }
107 });
108 };
109
110 return (
111 <Button
112 aria-label="Join"
113 className={className}
114 disabled={isSubmitting}
115 loading={isSubmitting}
116 onClick={handleJoin}
117 outline
118 size={small ? "sm" : "md"}
119 >
120 {title}
121 </Button>
122 );
123};
124
125export default Join;