Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
1import type { CollectActionType } from "@hey/types/hey";
2import { motion } from "motion/react";
3import type { Dispatch, SetStateAction } from "react";
4import { isAddress } from "viem";
5import LicensePicker from "@/components/Composer/LicensePicker";
6import ToggleWithHelper from "@/components/Shared/ToggleWithHelper";
7import { Button } from "@/components/Shared/UI";
8import { useCollectActionStore } from "@/store/non-persisted/post/useCollectActionStore";
9import { usePostLicenseStore } from "@/store/non-persisted/post/usePostLicenseStore";
10import { EXPANSION_EASE } from "@/variants";
11import AmountConfig from "./AmountConfig";
12import CollectLimitConfig from "./CollectLimitConfig";
13import FollowersConfig from "./FollowersConfig";
14import SplitConfig from "./SplitConfig";
15import TimeLimitConfig from "./TimeLimitConfig";
16
17interface CollectFormProps {
18 setShowModal: Dispatch<SetStateAction<boolean>>;
19}
20
21const CollectForm = ({ setShowModal }: CollectFormProps) => {
22 const { collectAction, setCollectAction, reset } = useCollectActionStore();
23 const { setLicense } = usePostLicenseStore();
24
25 const recipients = collectAction.payToCollect?.recipients || [];
26 const splitTotal = recipients.reduce((acc, { percent }) => acc + percent, 0);
27
28 const validationChecks = {
29 hasEmptyRecipients: recipients.some(({ address }) => !address),
30 hasImproperSplits: recipients.length > 1 && splitTotal !== 100,
31 hasInvalidEthAddress: recipients.some(
32 ({ address }) => address && !isAddress(address)
33 ),
34 hasZeroSplits: recipients.some(({ percent }) => percent === 0),
35 isRecipientsDuplicated:
36 new Set(recipients.map(({ address }) => address)).size !==
37 recipients.length
38 };
39
40 const setCollectType = (data: CollectActionType) => {
41 setCollectAction({ ...collectAction, ...data });
42 };
43
44 const toggleCollect = () => {
45 if (collectAction.enabled) {
46 setLicense(null);
47 reset();
48 } else {
49 setCollectType({ enabled: true });
50 }
51 };
52
53 const handleClose = () => {
54 setShowModal(false);
55 setLicense(null);
56 reset();
57 };
58
59 return (
60 <>
61 <div className="p-5">
62 <ToggleWithHelper
63 description="This post can be collected"
64 heading="Enable Collect"
65 on={collectAction.enabled || false}
66 setOn={toggleCollect}
67 />
68 </div>
69 <div className="divider" />
70 {collectAction.enabled && (
71 <>
72 <motion.div
73 animate="visible"
74 className="m-5 overflow-hidden"
75 initial="hidden"
76 transition={{ duration: 0.2, ease: EXPANSION_EASE }}
77 variants={{
78 hidden: { height: 0, opacity: 0, y: -20 },
79 visible: { height: "auto", opacity: 1, y: 0 }
80 }}
81 >
82 <AmountConfig setCollectType={setCollectType} />
83 {collectAction.payToCollect?.erc20?.value && (
84 <SplitConfig
85 isRecipientsDuplicated={validationChecks.isRecipientsDuplicated}
86 setCollectType={setCollectType}
87 />
88 )}
89 <CollectLimitConfig setCollectType={setCollectType} />
90 <TimeLimitConfig setCollectType={setCollectType} />
91 <FollowersConfig setCollectType={setCollectType} />
92 </motion.div>
93 <div className="divider" />
94 <div className="m-5">
95 <LicensePicker />
96 </div>
97 <div className="divider" />
98 </>
99 )}
100 <div className="flex space-x-2 p-5">
101 <Button className="ml-auto" onClick={handleClose} outline>
102 {collectAction.enabled ? "Reset" : "Cancel"}
103 </Button>
104 <Button
105 disabled={
106 (Number.parseFloat(
107 collectAction.payToCollect?.erc20?.value as string
108 ) <= 0 &&
109 collectAction.enabled) ||
110 Object.values(validationChecks).some(Boolean)
111 }
112 onClick={() => setShowModal(false)}
113 >
114 Save
115 </Button>
116 </div>
117 </>
118 );
119};
120
121export default CollectForm;