Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 3595 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
3596 stevensc 1
import React, { useCallback, useMemo, useState } from 'react';
2
import { useDispatch } from 'react-redux';
3
import { styled, Typography } from '@mui/material';
3595 stevensc 4
 
3596 stevensc 5
import { axios } from '@app/utils';
6
import { REACTIONS } from '@app/constants/feed';
7
import { addNotification } from '@app/redux/notification/notification.actions';
8
import colors from '@styles/config/colors';
3595 stevensc 9
 
10
const ReactionsBox = styled('div')(({ theme }) => ({
11
  position: 'absolute',
12
  bottom: '100%',
13
  backgroundColor: colors.main,
14
  border: `1px solid ${colors.border.primary}`,
15
  gap: theme.spacing(0.5),
16
  left: 0,
17
  display: 'flex',
18
  padding: theme.spacing(0.5),
19
  width: 'fit-content',
20
  borderRadius: theme.shape.borderRadius,
21
  transform: 'scale(0)',
22
  transformOrigin: 'center',
23
  transition: theme.transitions.create('transform', {
24
    duration: theme.transitions.duration.short,
25
    easing: theme.transitions.easing.easeInOut,
26
    delay: theme.transitions.duration.short
27
  }),
28
  '& > button': {
29
    transition: theme.transitions.create('transform', {
30
      duration: theme.transitions.duration.short,
31
      easing: theme.transitions.easing.easeInOut
32
    }),
33
    '&:hover': {
34
      transform: 'scale(1.1) translateY(-4px)'
35
    },
36
    svg: {
37
      fontSize: '32px'
38
    }
39
  }
3596 stevensc 40
}));
3595 stevensc 41
 
42
export function withReactions(Component) {
43
  const ReactionsButton = ({
44
    saveUrl = '',
45
    deleteUrl = '',
46
    currentReactionType = null,
47
    onReaction = () => null
48
  }) => {
3596 stevensc 49
    const [isHover, setIsHover] = useState(false);
50
    const dispatch = useDispatch();
3595 stevensc 51
 
52
    const currentReaction = useMemo(
53
      () => REACTIONS.find((r) => r.type === currentReactionType),
54
      [currentReactionType]
3596 stevensc 55
    );
56
    const Icon = currentReaction ? currentReaction.icon : REACTIONS[0].icon;
3595 stevensc 57
 
3596 stevensc 58
    const handleHover = () => setIsHover(!isHover);
3595 stevensc 59
 
60
    const saveReaction = useCallback(
61
      (type = 'r') => {
3596 stevensc 62
        const formData = new FormData();
63
        formData.append('reaction', type);
3595 stevensc 64
 
65
        axios.post(saveUrl, formData).then((res) => {
3596 stevensc 66
          const { success, data } = res.data;
3595 stevensc 67
 
68
          if (!success) {
3596 stevensc 69
            dispatch(addNotification({ style: 'danger', msg: data }));
3595 stevensc 70
          }
71
 
3596 stevensc 72
          onReaction(data, type);
73
        });
3595 stevensc 74
      },
75
      [saveUrl, dispatch]
3596 stevensc 76
    );
3595 stevensc 77
 
78
    const deleteReaction = useCallback(() => {
79
      axios.post(deleteUrl).then((res) => {
3596 stevensc 80
        const { success, data } = res.data;
3595 stevensc 81
 
82
        if (!success) {
3596 stevensc 83
          dispatch(addNotification({ style: 'danger', msg: data }));
84
          return;
3595 stevensc 85
        }
86
 
87
        onReaction({
88
          reactions: data.reactions,
89
          currentReactionType: ''
3596 stevensc 90
        });
91
      });
92
    }, []);
3595 stevensc 93
 
94
    return (
95
      <Component onClick={currentReaction ? deleteReaction : handleHover}>
3596 stevensc 96
        {currentReaction ? <Icon style={{ color: currentReaction.color }} /> : <Icon />}
3595 stevensc 97
 
3596 stevensc 98
        <Typography sx={{ display: { xs: 'none', md: 'inline-flex' } }} variant='overline'>
3595 stevensc 99
          {currentReaction ? currentReaction.label : 'Reaccionar'}
100
        </Typography>
101
 
102
        <ReactionsBox
103
          sx={{
104
            transform: isHover ? 'scale(1)' : 'scale(0)',
105
            transformOrigin: 'center'
106
          }}
107
        >
108
          {REACTIONS.map(({ type, label, icon: Icon, color }) => (
109
            <button
110
              key={type}
111
              title={label}
112
              onClickCapture={(e) => {
3596 stevensc 113
                e.stopPropagation();
114
                saveReaction(type);
3595 stevensc 115
              }}
116
            >
117
              <Icon style={{ color }} />
118
            </button>
119
          ))}
120
        </ReactionsBox>
121
      </Component>
3596 stevensc 122
    );
123
  };
3595 stevensc 124
 
3596 stevensc 125
  return ReactionsButton;
3595 stevensc 126
}