Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 3596 | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

import React, { useCallback, useMemo, useState } from 'react';
import { useDispatch } from 'react-redux';
import { styled, Typography } from '@mui/material';

import { axios } from '@app/utils';
import { REACTIONS } from '@app/constants/feed';
import { addNotification } from '@app/redux/notification/notification.actions';
import colors from '@styles/config/colors';

const ReactionsBox = styled('div')(({ theme }) => ({
  position: 'absolute',
  bottom: '100%',
  backgroundColor: colors.main,
  border: `1px solid ${colors.border.primary}`,
  gap: theme.spacing(0.5),
  left: 0,
  display: 'flex',
  padding: theme.spacing(0.5),
  width: 'fit-content',
  borderRadius: theme.shape.borderRadius,
  transform: 'scale(0)',
  transformOrigin: 'center',
  transition: theme.transitions.create('transform', {
    duration: theme.transitions.duration.short,
    easing: theme.transitions.easing.easeInOut,
    delay: theme.transitions.duration.short
  }),
  '& > button': {
    transition: theme.transitions.create('transform', {
      duration: theme.transitions.duration.short,
      easing: theme.transitions.easing.easeInOut
    }),
    '&:hover': {
      transform: 'scale(1.1) translateY(-4px)'
    },
    svg: {
      fontSize: '32px'
    }
  }
}));

export function withReactions(Component) {
  const ReactionsButton = ({
    saveUrl = '',
    deleteUrl = '',
    currentReactionType = null,
    onReaction = () => null
  }) => {
    const [isHover, setIsHover] = useState(false);
    const dispatch = useDispatch();

    const currentReaction = useMemo(
      () => REACTIONS.find((r) => r.type === currentReactionType),
      [currentReactionType]
    );
    const Icon = currentReaction ? currentReaction.icon : REACTIONS[0].icon;

    const handleHover = () => setIsHover(!isHover);

    const saveReaction = useCallback(
      (type = 'r') => {
        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 }));
          }

          onReaction(data, type);
        });
      },
      [saveUrl, dispatch]
    );

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

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

        onReaction({
          reactions: data.reactions,
          currentReactionType: ''
        });
      });
    }, []);

    return (
      <Component onClick={currentReaction ? deleteReaction : handleHover}>
        {currentReaction ? <Icon style={{ color: currentReaction.color }} /> : <Icon />}

        <Typography sx={{ display: { xs: 'none', md: 'inline-flex' } }} variant='overline'>
          {currentReaction ? currentReaction.label : 'Reaccionar'}
        </Typography>

        <ReactionsBox
          sx={{
            transform: isHover ? 'scale(1)' : 'scale(0)',
            transformOrigin: 'center'
          }}
        >
          {REACTIONS.map(({ type, label, icon: Icon, color }) => (
            <button
              key={type}
              title={label}
              onClickCapture={(e) => {
                e.stopPropagation();
                saveReaction(type);
              }}
            >
              <Icon style={{ color }} />
            </button>
          ))}
        </ReactionsBox>
      </Component>
    );
  };

  return ReactionsButton;
}