Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 634 | Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
633 stevensc 1
import React, { useEffect, useRef, useState } from "react";
2
import { useDispatch } from "react-redux";
3
import { axios, debounce } from "../utils";
4
import { addNotification } from "store/notification/notification.actions";
5
import useOutsideClick from "hooks/useOutsideClick";
6
 
7
import ReactionIcon from "@mui/icons-material/Recommend";
8
import FunIcon from "../components/UI/icons/Fun";
9
import LoveItIcon from "../components/UI/icons/LoveIt";
10
import SupportIcon from "../components/UI/icons/Support";
11
import InterestIcon from "../components/UI/icons/Interest";
12
import RecommendIcon from "../components/UI/icons/Recommned";
13
 
14
const initialReaction = {
15
  label: "Reaccionar",
16
  icon: ReactionIcon,
17
  type: "default",
18
};
19
 
20
export default function withReactions(
21
  Component = <></>,
22
  { saveUrl = "", deleteUrl = "", currentReaction = "default" } = {}
23
) {
24
  return function (props) {
25
    const [reaction, setReaction] = useState(initialReaction);
26
    const [isHover, setIsHover] = useState(false);
27
    const rectionBtn = useRef(null);
28
    const dispatch = useDispatch();
29
    useOutsideClick(rectionBtn, () => setIsHover(false));
30
 
31
    const reactions = [
32
      {
33
        type: "r",
34
        icon: RecommendIcon,
35
        label: "Me gusta",
36
      },
37
      {
38
        type: "s",
39
        icon: SupportIcon,
40
        label: "Dar apoyo",
41
      },
42
      {
43
        type: "l",
44
        icon: LoveItIcon,
45
        label: "Me encanta",
46
      },
47
      {
48
        type: "i",
49
        icon: InterestIcon,
50
        label: "Me interesa",
51
      },
52
      {
53
        type: "f",
54
        icon: FunIcon,
55
        label: "Me divierte",
56
      },
57
    ];
58
 
59
    const saveReaction = (type) => {
60
      const formData = new FormData();
61
      formData.append("reaction", type);
62
 
63
      axios.post(saveUrl, formData).then((res) => {
64
        const { success, data } = res.data;
65
 
66
        if (!success) {
67
          dispatch(addNotification({ style: "danger", msg: data }));
68
          return;
69
        }
70
 
71
        const newReaction = reactions.find(
72
          (reaction) => reaction.type === type
73
        );
74
        setReaction(newReaction);
75
      });
76
    };
77
 
78
    const deleteReaction = () => {
79
      axios.post(deleteUrl).then((res) => {
80
        const { success, data } = res.data;
81
 
82
        if (!success) {
83
          dispatch(addNotification({ style: "danger", msg: data }));
84
          return;
85
        }
86
 
87
        setReaction(initialReaction);
88
      });
89
    };
90
 
91
    const onHover = debounce(() => setIsHover(true), 500);
92
 
93
    const onUnhover = debounce(() => setIsHover(false), 500);
94
 
95
    useEffect(() => {
96
      const currentOption = reactions.find(
97
        ({ type }) => type === currentReaction
98
      );
99
 
100
      if (!currentOption) {
101
        setReaction(initialReaction);
102
        return;
103
      }
104
 
105
      setReaction(currentOption);
106
    }, [currentReaction]);
107
 
108
    return (
109
      <Component
110
        onMouseOver={onHover}
111
        onMouseOut={onUnhover}
112
        ref={rectionBtn}
113
        icon={reaction.icon}
114
        onClick={() =>
115
          reaction.type !== "default"
116
            ? deleteReaction()
117
            : saveReaction(reactions[0].type)
118
        }
119
        {...props}
120
      >
121
        {isHover && (
122
          <div className={`reactions ${isHover ? "active" : ""}`}>
123
            {reactions.map(({ icon: Icon, type, label }) => (
124
              <button
125
                key={type}
126
                onClick={(e) => {
127
                  e.stopPropagation();
128
                  saveReaction(type);
129
                  setIsHover(false);
130
                }}
131
                title={label}
132
              >
133
                <Icon />
134
              </button>
135
            ))}
136
          </div>
137
        )}
138
      </Component>
139
    );
140
  };
141
}