Proyectos de Subversion LeadersLinked - SPA

Rev

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

Rev Autor Línea Nro. Línea
200 stevensc 1
import React, { useEffect, useState } from "react";
2
import { axios } from "../../utils";
3
import { useLocation } from "react-router-dom";
4
import { getBackendVars } from "../../services/backendVars";
5
import { addNotification } from "../../redux/notification/notification.actions";
6
import { Col, Container, Row } from "react-bootstrap";
7
import { useDispatch, useSelector } from "react-redux";
8
import parse from "html-react-parser";
9
import TungstenIcon from "@mui/icons-material/Tungsten";
10
import RecommendIcon from "@mui/icons-material/Recommend";
11
import AccessTimeIcon from "@mui/icons-material/AccessTime";
12
import FavoriteIcon from "@mui/icons-material/FavoriteTwoTone";
13
import SendOutlinedIcon from "@mui/icons-material/SendOutlined";
14
import ChatOutlinedIcon from "@mui/icons-material/ChatOutlined";
15
import EmojiEmotionsIcon from "@mui/icons-material/EmojiEmotions";
16
import VolunteerActivismIcon from "@mui/icons-material/VolunteerActivism";
5 stevensc 17
 
200 stevensc 18
import {
19
  CommentForm,
20
  CommentsList,
21
} from "../../components/feed/CommentSection";
22
import HomeNews from "../../components/widgets/default/HomeNews";
23
import InputOption from "../../components/dashboard/linkedin/action-button/InputOption";
24
import ReactionsButton from "../../components/UI/buttons/ReactionsButton";
25
import withExternalShare from "../../components/dashboard/linkedin/withExternalShare";
5 stevensc 26
 
27
const PostViewPage = () => {
200 stevensc 28
  const [post, setPost] = useState({});
29
  const [totalSends, setTotalSends] = useState(0);
30
  const [reactions, setReactions] = useState([]);
31
  const [myReaction, setMyReaction] = useState("");
32
  const [totalReactions, setTotalReactions] = useState(0);
33
  const [comments, setComments] = useState([]);
34
  const [readMore, setReadMore] = useState(false);
35
  const [showComments, setShowComments] = useState(false);
36
  const labels = useSelector(({ intl }) => intl.labels);
37
  const dispatch = useDispatch();
38
  const { pathname } = useLocation();
5 stevensc 39
 
40
  const reactionsOptions = [
41
    {
200 stevensc 42
      type: "r",
43
      icon: <RecommendIcon style={{ color: "#7405f9" }} />,
5 stevensc 44
    },
45
    {
200 stevensc 46
      type: "s",
47
      icon: <VolunteerActivismIcon style={{ color: "#6495ED" }} />,
5 stevensc 48
    },
49
    {
200 stevensc 50
      type: "l",
51
      icon: <FavoriteIcon style={{ color: "#DF704D" }} />,
5 stevensc 52
    },
53
    {
200 stevensc 54
      type: "i",
5 stevensc 55
      icon: (
56
        <TungstenIcon
200 stevensc 57
          style={{ color: "#F5BB5C", transform: "rotate(180deg)" }}
5 stevensc 58
        />
59
      ),
60
    },
61
    {
200 stevensc 62
      type: "f",
63
      icon: <EmojiEmotionsIcon style={{ color: "#FF7F50" }} />,
5 stevensc 64
    },
200 stevensc 65
  ];
5 stevensc 66
 
200 stevensc 67
  const readMoreHandler = () => setReadMore(!readMore);
5 stevensc 68
 
69
  const displayCommentSection = () => {
200 stevensc 70
    setShowComments(!showComments);
71
  };
5 stevensc 72
 
73
  const getComments = () => {
74
    axios.get(post.comments_url).then((response) => {
200 stevensc 75
      const { data, success } = response.data;
5 stevensc 76
 
77
      if (!success) {
78
        const errorMessage =
200 stevensc 79
          typeof data === "string" ? data : "Error interno. Intente más tarde.";
5 stevensc 80
 
200 stevensc 81
        dispatch(addNotification({ style: "danger", msg: errorMessage }));
82
        return;
5 stevensc 83
      }
84
 
200 stevensc 85
      setComments(data);
86
    });
87
  };
5 stevensc 88
 
89
  const handleExternalShare = (value) => {
200 stevensc 90
    setTotalSends(value);
91
  };
5 stevensc 92
 
93
  const ExternalShareButton = withExternalShare(
94
    InputOption,
95
    post.share_external_url,
96
    {
97
      Icon: SendOutlinedIcon,
200 stevensc 98
      color: "gray",
99
      title: "Enviar",
5 stevensc 100
      shareUrl: post.share_increment_external_counter_url,
101
      setValue: handleExternalShare,
102
      withTitle: true,
103
    }
200 stevensc 104
  );
5 stevensc 105
 
106
  const htmlParsedText = (fullStringText) => {
200 stevensc 107
    const fullText = parse(fullStringText);
5 stevensc 108
    if (fullStringText.length > 500) {
200 stevensc 109
      const shortenedString = fullStringText.substr(0, 500);
110
      const shortenedText = parse(`${shortenedString}... `);
5 stevensc 111
      return (
112
        <>
113
          {readMore ? fullText : shortenedText}
114
          <span className="cursor-pointer" onClick={readMoreHandler}>
200 stevensc 115
            {readMore ? " Leer menos" : " Leer más"}
5 stevensc 116
          </span>
117
        </>
200 stevensc 118
      );
5 stevensc 119
    }
200 stevensc 120
    return <p>{fullText}</p>;
121
  };
5 stevensc 122
 
123
  const addComment = ({ comment }) => {
200 stevensc 124
    const formData = new FormData();
125
    formData.append("comment", comment);
5 stevensc 126
 
127
    axios.post(post.comments_add_url, formData).then((response) => {
200 stevensc 128
      const { success, data } = response.data;
5 stevensc 129
 
130
      if (!success) {
131
        const errorMessage =
200 stevensc 132
          typeof data === "string" ? data : "Error interno. Intente más tarde.";
5 stevensc 133
 
200 stevensc 134
        dispatch(addNotification({ style: "danger", msg: errorMessage }));
135
        return;
5 stevensc 136
      }
137
 
200 stevensc 138
      setComments((prevMessages) => [...prevMessages, data]);
139
    });
140
  };
5 stevensc 141
 
142
  const deleteComment = (commentUnique, deleteCommentUrl) => {
143
    axios
144
      .post(deleteCommentUrl)
145
      .then((response) => {
200 stevensc 146
        const { success, data } = response.data;
5 stevensc 147
 
148
        if (!success) {
149
          const errorMessage =
200 stevensc 150
            typeof data === "string"
5 stevensc 151
              ? data
200 stevensc 152
              : "Error interno. Intente más tarde.";
5 stevensc 153
 
200 stevensc 154
          dispatch(addNotification({ style: "danger", msg: errorMessage }));
155
          return;
5 stevensc 156
        }
157
 
158
        setComments((prevComments) =>
159
          prevComments.filter((comment) => comment.unique !== commentUnique)
200 stevensc 160
        );
161
        dispatch(addNotification({ style: "success", msg: data }));
5 stevensc 162
      })
163
      .catch((error) => {
200 stevensc 164
        dispatch(addNotification({ style: "danger", msg: error }));
165
        throw new Error(error);
166
      });
167
  };
5 stevensc 168
 
169
  useEffect(() => {
170
    getBackendVars(pathname)
171
      .then((post) => {
200 stevensc 172
        setMyReaction(post.my_reaction);
173
        setTotalSends(post.total_share_external);
174
        setPost(post);
5 stevensc 175
      })
176
      .catch((error) => {
177
        dispatch(
178
          addNotification({
200 stevensc 179
            style: "danger",
180
            message: "Error interno. Por favor, inténtelo de nuevo más tarde.",
5 stevensc 181
          })
200 stevensc 182
        );
183
        throw new Error(error);
184
      });
185
  }, []);
5 stevensc 186
 
187
  useEffect(() => {
188
    if (showComments && !comments.length) {
200 stevensc 189
      getComments();
5 stevensc 190
    }
200 stevensc 191
  }, [showComments]);
5 stevensc 192
 
193
  useEffect(() => {
194
    const feedReactions = reactions.reduce(
195
      (acc, reaction) => acc + Number(reaction.total),
196
 
200 stevensc 197
    );
5 stevensc 198
 
200 stevensc 199
    setTotalReactions(feedReactions);
200
  }, [reactions]);
5 stevensc 201
 
202
  return (
203
    <Container>
204
      <Row>
205
        <Col md="8">
206
          <div className="feed">
207
            <div className="feed__body">
208
              {post.image && (
209
                <img
210
                  src={`/storage/type/post/code/${post.uuid}/filename/${post.image}`}
211
                />
212
              )}
213
            </div>
214
            <div className="feed__body">
215
              <div className="feed__header">
216
                <div className="feed__info">
217
                  <h2>{post.title}</h2>
218
                  <div className="time__elapse">
219
                    <p>{post.addedOn}</p>
220
                    <AccessTimeIcon className="time__elapse-icon" />
221
                  </div>
222
                </div>
223
              </div>
224
              {post.description && htmlParsedText(post.description)}
225
              {post.file && (
226
                <a href={post.file} download>
227
                  <img
228
                    className="pdf"
229
                    src="/images/extension/pdf.png"
230
                    alt="pdf"
231
                  />
232
                </a>
233
              )}
234
            </div>
235
            <div className="d-flex justify-content-between align-items-center px-3">
236
              <div className="reactions-counter">
237
                {reactionsOptions
238
                  .filter((option) =>
239
                    reactions.find(({ reaction }) => reaction === option.type)
240
                  )
241
                  .map((reaction) => reaction.icon)}
242
                <span>{totalReactions} reacciones</span>
243
              </div>
244
              {!!totalSends && (
245
                <span>{`${totalSends} ${labels.sends?.toLowerCase()}`}</span>
246
              )}
247
            </div>
248
            <div className="feed__buttons">
249
              <ReactionsButton
250
                className="btn feed__share-option position-relative"
251
                currentReaction={myReaction}
252
                withLabel
253
                onChange={({ reactions }) => setReactions(reactions)}
254
              />
255
              <InputOption
256
                Icon={ChatOutlinedIcon}
257
                title={labels.comments}
258
                color="gray"
259
                onClick={displayCommentSection}
260
                withTitle
261
              />
262
              <ExternalShareButton />
263
            </div>
264
            {showComments && (
265
              <>
266
                <CommentForm onSubmit={addComment} />
267
                <CommentsList comments={comments} onDelete={deleteComment} />
268
              </>
269
            )}
270
          </div>
271
        </Col>
272
        <Col md="4">
273
          <HomeNews currentPost={post.uuid} />
274
        </Col>
275
      </Row>
276
    </Container>
200 stevensc 277
  );
278
};
5 stevensc 279
 
200 stevensc 280
export default PostViewPage;