Proyectos de Subversion LeadersLinked - SPA

Rev

Autoría | Ultima modificación | Ver Log |

import React, { useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { connect } from "react-redux";
import { styled } from "@mui/material";
import { CheckCircle } from "@mui/icons-material";
import parse from "html-react-parser";

import { axios } from "@app/utils";
import { addNotification } from "@app/redux/notification/notification.actions";
import { useFetch } from "@hooks";

import { FILE_TYPE_LABELS } from "@app/constants/files";

import Button from "@app/components/UI/buttons/Buttons";
import Spinner from "@app/components/UI/Spinner";
import WidgetWrapper from "@app/components/widgets/WidgetLayout";
import MicrolearningLayout from "@app/layouts/micro-learning/GoBack";

const Slide = styled(WidgetWrapper)`
  margin: auto;
  width: fit-content;
  svg {
    position: absolute;
    top: 1rem;
    right: 1rem;
  }
  img,
  video {
    max-width: 400px;
    max-height: 400px;
    object-fit: contain;
  }
  button {
    position: absolute;
    bottom: 1rem;
    right: 1rem;
  }
`;

const SlideViewPage = ({ addNotification }) => {
  const { uuid } = useParams();
  const {
    data: slide,
    isLoading,
    mutate,
  } = useFetch(`/microlearning/get-slide/${uuid}`, {});
  const [displayFile, setDisplayFile] = useState(false);
  const navigate = useNavigate();

  const closeParent = async (url = "") => {
    const response = await axios.post(url);
    const { data, success } = response.data;

    if (!success) {
      const errorMessage =
        typeof data === "string"
          ? data
          : Object.entries(data)
              .map(([key, value]) => `${key}: ${value}`)
              .join(", ");
      throw new Error(errorMessage);
    }

    const resMsg = data.message ?? data;
    addNotification({ style: "success", msg: resMsg });
  };

  const markCompleted = async () => {
    try {
      const response = await axios.post(slide?.link_sync);
      const { data, success } = response.data;

      if (!success) {
        const errorMessage =
          typeof data === "string"
            ? data
            : Object.entries(data)
                .map(([key, value]) => `${key}: ${value}`)
                .join(", ");
        throw new Error(errorMessage);
      }

      if (data.link_close_capsule) {
        await closeParent(data?.link_close_capsule);
        navigate("/microlearning");
      }

      if (data.link_close_topic) {
        await closeParent(data?.link_close_topic);
      }

      const resMsg = data.message ?? data;
      addNotification({ style: "success", msg: resMsg });
      mutate({ ...slide, completed: 1 });
    } catch (error) {
      addNotification({ style: "danger", msg: error.message });
    } finally {
      setDisplayFile(false);
    }
  };

  const renderFile = (type = "video") => {
    switch (type) {
      case "video": {
        return (
          <>
            {displayFile ? (
              <video controls controlsList="nodownload" onEnded={markCompleted}>
                <source src={slide?.file} />
              </video>
            ) : (
              <>
                <img src={slide?.background} alt={slide?.name} />
                <Button
                  color="primary"
                  onClick={() => setDisplayFile(!displayFile)}
                >
                  {FILE_TYPE_LABELS[slide?.type]}
                </Button>
              </>
            )}
          </>
        );
      }

      case "image": {
        return <img src={slide?.file} alt={slide?.name} />;
      }

      case "audio": {
        return (
          <>
            {displayFile ? (
              <audio
                controls
                src={slide?.file}
                alt={slide?.name}
                onEnded={markCompleted}
              />
            ) : (
              <>
                <img src={slide?.background} alt={slide?.name} />
                <Button
                  color="primary"
                  onClick={() => setDisplayFile(!displayFile)}
                >
                  {FILE_TYPE_LABELS[slide?.type]}
                </Button>
              </>
            )}
          </>
        );
      }

      case "text": {
        return parse(slide?.description);
      }

      case "document": {
        return (
          <a href={slide?.file} target="_blank" rel="noreferrer">
            <img className="pdf" src="/images/extension/pdf.png" alt="pdf" />
          </a>
        );
      }

      default:
        return (
          <>
            {displayFile ? (
              <video controls controlsList="nodownload" onEnded={markCompleted}>
                <source src={slide?.file} />
              </video>
            ) : (
              <>
                <img src={slide?.background} alt={slide?.name} />
                <Button
                  color="primary"
                  onClick={() => setDisplayFile(!displayFile)}
                >
                  {FILE_TYPE_LABELS[slide?.type]}
                </Button>
              </>
            )}
          </>
        );
    }
  };

  if (isLoading) {
    return <Spinner />;
  }

  return (
    <MicrolearningLayout title={slide?.name}>
      <Slide>
        {slide?.completed && !displayFile ? (
          <CheckCircle color="success" />
        ) : null}
        {renderFile(slide?.type)}
      </Slide>

      <Button
        color="primary"
        disabled={slide?.completed}
        onClick={() => markCompleted()}
        sx={{ width: "100%", mt: 2 }}
      >
        Marcar como completado
      </Button>
    </MicrolearningLayout>
  );
};

const mapDispatchToProps = {
  addNotification: (notification) => addNotification(notification),
};

export default connect(null, mapDispatchToProps)(SlideViewPage);