MCPcopy Create free account
hub / github.com/dfinity/cancan / TippingButton

Function TippingButton

src/components/TippingButton.tsx:10–91  ·  view source on GitHub ↗
({
  senderId,
  currentRewardPoints,
  recipientId,
  onRefreshUser,
})

Source from the content-addressed store, hash-verified

8const DEFAULT_TIPPING_AMOUNT = 1;
9
10export default function TippingButton({
11 senderId,
12 currentRewardPoints,
13 recipientId,
14 onRefreshUser,
15}) {
16 const [isDisabled, setDisabled] = useState(false);
17 const [activeAnimations, setActiveAnimations] = useState<number[] | []>([]);
18 const [animationId, setAnimationId] = useState(0);
19 const [localRewardPoints, setRewardPoints] = useState(currentRewardPoints);
20 const [tippingPoints, setTippingPoints] = useState(1);
21
22 // The save tipping function gets debounced so it collects tips from the last
23 // 5 seconds and applies them all at once. If the amount of tips is over a
24 // certain threshold, show the user a confirmation.
25 const saveTipping = async (localTippingPoints) => {
26 setTippingPoints(1);
27 await putRewardTransfer(senderId, recipientId, BigInt(localTippingPoints));
28 onRefreshUser();
29 };
30 const saveTippingDebounced = useRef(debounce(saveTipping, 3000));
31
32 // On click store the accumulated tipping points for multiple clicks and call
33 // the debounced tip saving function to save on the backend
34 const handleClick = async (ev) => {
35 ev.preventDefault();
36 if (isDisabled) return;
37 setRewardPoints(localRewardPoints - DEFAULT_TIPPING_AMOUNT);
38 setTippingPoints(tippingPoints + DEFAULT_TIPPING_AMOUNT);
39 saveTippingDebounced.current(tippingPoints);
40 setAnimationId((prevId) => prevId + 1);
41 const currentId = animationId;
42 setActiveAnimations((prev) => [...prev, currentId]);
43 setTimeout(() => {
44 setActiveAnimations((prev) => prev.filter((id) => id !== currentId));
45 }, 4000);
46 };
47
48 useEffect(() => {
49 setRewardPoints(currentRewardPoints);
50 if (currentRewardPoints < DEFAULT_TIPPING_AMOUNT) {
51 setDisabled(true);
52 }
53 }, [currentRewardPoints]);
54
55 useEffect(() => {
56 if (senderId === recipientId) setDisabled(true);
57 }, []);
58
59 return (
60 <span
61 className="TippingButton"
62 onClick={handleClick}
63 style={{
64 pointerEvents: isDisabled ? "none" : "all",
65 cursor: isDisabled ? "default" : "pointer",
66 opacity: isDisabled ? 0.5 : 1,
67 }}

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected