Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 645 | Rev 752 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

import React, { useEffect, useRef, useState } from "react";
import { useDispatch } from "react-redux";
import { axios, debounce } from "../utils";
import { addNotification } from "store/notification/notification.actions";
import useOutsideClick from "hooks/useOutsideClick";

import ReactionIcon from "@mui/icons-material/Recommend";
import FunIcon from "../components/UI/icons/Fun";
import LoveItIcon from "../components/UI/icons/LoveIt";
import SupportIcon from "../components/UI/icons/Support";
import InterestIcon from "../components/UI/icons/Interest";
import RecommendIcon from "../components/UI/icons/Recommned";

const initialReaction = {
  label: "Reaccionar",
  icon: ReactionIcon,
  type: "default",
};

export default function withReactions(
  Component = <></>,
  {
    saveUrl = "",
    deleteUrl = "",
    currentReaction = "default",
    onSelect = () => null,
  } = {}
) {
  return function (props) {
    const [reaction, setReaction] = useState(initialReaction);
    const [isHover, setIsHover] = useState(false);
    const rectionBtn = useRef(null);
    const dispatch = useDispatch();
    useOutsideClick(rectionBtn, () => setIsHover(false));

    const reactions = [
      {
        type: "r",
        icon: RecommendIcon,
        label: "Me gusta",
      },
      {
        type: "s",
        icon: SupportIcon,
        label: "Dar apoyo",
      },
      {
        type: "l",
        icon: LoveItIcon,
        label: "Me encanta",
      },
      {
        type: "i",
        icon: InterestIcon,
        label: "Me interesa",
      },
      {
        type: "f",
        icon: FunIcon,
        label: "Me divierte",
      },
    ];

    const saveReaction = (type) => {
      const formData = new FormData();
      formData.append("reaction", type);

      axios.post(saveUrl, formData).then((res) => {
        const { success, data } = res.data;

        if (!success) {
          dispatch(addNotification({ style: "danger", msg: data }));
          return;
        }

        const newReaction = reactions.find((r) => r.type === type);

        setReaction(newReaction);
        onSelect(data.reactions);
      });
    };

    const deleteReaction = () => {
      axios.post(deleteUrl).then((res) => {
        const { success, data } = res.data;

        if (!success) {
          dispatch(addNotification({ style: "danger", msg: data }));
          return;
        }

        setReaction(initialReaction);
        onSelect(data.reactions);
      });
    };

    const onHover = debounce(() => setIsHover(true), 500);

    const onUnhover = debounce(() => setIsHover(false), 500);

    useEffect(() => {
      const currentOption = reactions.find(
        ({ type }) => type === currentReaction
      );

      if (!currentOption) {
        setReaction(initialReaction);
        return;
      }

      setReaction(currentOption);
    }, [currentReaction]);

    return (
      <Component
        onMouseOver={onHover}
        onMouseOut={onUnhover}
        ref={rectionBtn}
        icon={reaction.icon}
        onClick={() =>
          reaction.type !== "default"
            ? deleteReaction()
            : saveReaction(reactions[0].type)
        }
        label={reaction.label}
        {...props}
      >
        {isHover && (
          <div className={`reactions ${isHover ? "active" : ""}`}>
            {reactions.map(({ icon: Icon, type, label }) => (
              <button
                key={type}
                onClick={(e) => {
                  e.stopPropagation();
                  saveReaction(type);
                  setIsHover(false);
                }}
                title={label}
              >
                <Icon />
              </button>
            ))}
          </div>
        )}
      </Component>
    );
  };
}