Skip to content
Snippets Groups Projects
CollectionCommentSection.js 11.4 KiB
Newer Older
Raul Almeida's avatar
Raul Almeida committed
/*Copyright (C) 2019 Centro de Computacao Cientifica e Software Livre
Departamento de Informatica - Universidade Federal do Parana

This file is part of Plataforma Integrada MEC.

Plataforma Integrada MEC is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Plataforma Integrada MEC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Plataforma Integrada MEC.  If not, see <http://www.gnu.org/licenses/>.*/

import React, { useRef, useState, useEffect, Fragment } from 'react';
Raul Almeida's avatar
Raul Almeida committed
import { Grid } from '@material-ui/core';
import Card from '@material-ui/core/Card';
Raul Almeida's avatar
Raul Almeida committed
import Button from '@material-ui/core/Button';
import EditIcon from '@material-ui/icons/Edit';
Raul Almeida's avatar
Raul Almeida committed
import styled from 'styled-components';
import CommentForm from './ResourcePageComponents/CommentForm.js';
import Comment from './Comment.js';
import Snackbar from '@material-ui/core/Snackbar';
import MuiAlert from '@material-ui/lab/Alert';
lfr20's avatar
lfr20 committed
import { getRequest } from '../Components/HelperFunctions/getAxiosConfig'
import ExitToAppIcon from '@material-ui/icons/ExitToApp';
import SignUpModal from './SignUpModal.js';
import LoginModal from './LoginModal.js';
import SnackBarComponent from './SnackbarComponent';
lfr20's avatar
lfr20 committed
import CircularProgress from '@material-ui/core/CircularProgress';
import IconButton from '@material-ui/core/IconButton';
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
Raul Almeida's avatar
Raul Almeida committed

import { Comentarios } from "ImportImages.js";
Raul Almeida's avatar
Raul Almeida committed
export default function CollectionCommentSection(props) {
	const [post_snack_open, setPostSnackOpen] = useState(false);
	const [delete_snack_open, setDeleteSnackOpen] = useState(false);
	const [render_state, setRenderState] = useState(0);
lfr20's avatar
lfr20 committed
	const [sign_up_open, setSignUpOpen] = useState(false);
	const [log_in_open, setLoginOpen] = useState(false);
lfr20's avatar
lfr20 committed
	const [is_loading, setIsLoading] = useState(false);
lfr20's avatar
lfr20 committed
	const [snackInfo, setSnackInfo] = useState({
		open: false,
		text: '',
		severity: '',
		color: ''
	});
	const [reviews, setReviews] = useState([]);
lfr20's avatar
lfr20 committed
	const [totalReviews, setTotalReviews] = useState(0);
	const [currPageReviews, setCurrPageReviews] = useState(0);
Raul Almeida's avatar
Raul Almeida committed
	const comment_ref = useRef(null);
	const forceUpdate = () => { setCurrPageReviews(0); setRenderState(render_state + 1); }
	const handlePostSnackbar = () => {
		setPostSnackOpen(!post_snack_open);
	}

	const handleDeleteSnackbar = () => {
		setDeleteSnackOpen(!delete_snack_open);
	}

Raul Almeida's avatar
Raul Almeida committed
	const handleScrollToCommentForm = () => {
		window.scrollTo(0, comment_ref.current.offsetTop);
	}

lfr20's avatar
lfr20 committed
	function handleOpenSnackSignIn() {
		const info = {
			open: true,
			text: 'Você foi logado com sucesso!',
			severity: 'success',
			color: '',
		}

		handleSnackInfo(info)
	}

	function handleSnackInfo(info) {
		setSnackInfo({
			...info
		})
	}

	function handleCloseSnack() {
		setSnackInfo({
			open: false,
			text: '',
			severity: '',
			color: '',
		})
	}

	function handleOpenSignUp() {
		setSignUpOpen(true)
	}

	function Alert(props) {
		return <MuiAlert elevation={6} variant="filled" {...props} />;
	}

lfr20's avatar
lfr20 committed
	function handleLoadMoreReviews() {
		if (reviews.length !== parseInt(totalReviews))
			setCurrPageReviews((previous) => previous + 1)
		else {
			const info = {
				open: true,
				text: 'Não há mais comentários para carregar.',
				severity: 'warning',
				color: '',
			}
			handleSnackInfo(info)
		}
	}

lfr20's avatar
lfr20 committed
	const NoCommentsMessage = (contrast) => {
lfr20's avatar
lfr20 committed
		const NoCommentsContainer = styled.div`
Raul Almeida's avatar
Raul Almeida committed
			text-align: center;
			margin-left: 9vw;
			margin-right: 9vw;
		`
lfr20's avatar
lfr20 committed
		const BlueTitle = styled.h2`
lfr20's avatar
lfr20 committed
			color: ${props => props.contrast === "" ? "#673ab7" : "white"};
lfr20's avatar
lfr20 committed
		const Secondary = styled.h3`
Raul Almeida's avatar
Raul Almeida committed
			font-weight: 100;
lfr20's avatar
lfr20 committed
			color: ${props => props.contrast === "" ? "black" : "white"};
lfr20's avatar
lfr20 committed
		const ButtonText = styled.span`
Raul Almeida's avatar
Raul Almeida committed
			font-weight: 900;
lfr20's avatar
lfr20 committed
			color: ${props => props.contrast === "" ? "white" : "yellow"};
			text-decoration: ${props => props.contrast === "" ? "none" : "underline"};
lfr20's avatar
lfr20 committed
		const Image = styled.img`
Raul Almeida's avatar
Raul Almeida committed
		`
		return (
			<NoCommentsContainer>
				<Image src={Comentarios} style={{ width: "100%", maxWidth: 234 }} />
lfr20's avatar
lfr20 committed
				<BlueTitle contrast={contrast}>Compartilhe sua opinião com a rede!</BlueTitle>
				<Secondary contrast={contrast}>Gostou desta coleção? Comente e compartilhe com a rede sua opinião. Interagindo com a rede, você contribui para que mais coleções como esta sejam criadas.</Secondary>
Raul Almeida's avatar
Raul Almeida committed
				<Button
					variant="contained"
					color="primary"
lfr20's avatar
lfr20 committed
					style={contrast.contrast === "" ? {} : { backgroundColor: "black", border: "1px solid white" }}
Raul Almeida's avatar
Raul Almeida committed
					startIcon={<EditIcon />}
					onClick={handleScrollToCommentForm}
				>
lfr20's avatar
lfr20 committed
					<ButtonText contrast={contrast}>Relatar experiência</ButtonText>
Raul Almeida's avatar
Raul Almeida committed
				</Button>
			</NoCommentsContainer>
		);
	}
lfr20's avatar
lfr20 committed
	const CollectionComments = (contrast) => {
Raul Almeida's avatar
Raul Almeida committed
		return (
lfr20's avatar
lfr20 committed
			<ComentariosBox contrast={contrast}>
lfr20's avatar
lfr20 committed
				<h3>{totalReviews} {totalReviews !== 1 ? 'Relatos' : 'Relato'} sobre o uso do Recurso</h3>
Raul Almeida's avatar
Raul Almeida committed
				{reviews.map(r => {
					return (
lfr20's avatar
lfr20 committed
						<div className="comentario-template" key={r.created_at}>
							<Comment
lfr20's avatar
lfr20 committed
								contrast={contrast}
lfr20's avatar
lfr20 committed
								isCollection={false}
								rerenderCallback={forceUpdate}
								objectID={props.id}
								reviewID={r.id}
								reviewRatings={r.review_ratings}
								authorID={r.user.id}
								rating={r.rating_average}
								authorName={r.user.name}
								authorAvatar={r.user.avatar}
								description={r.description}
								createdAt={r.created_at}
								handleSnackbar={handleDeleteSnackbar}
								handlePost={handlePostSnackbar}
								recurso={false}
							/>
						</div>
lfr20's avatar
lfr20 committed
					);
				})}
lfr20's avatar
lfr20 committed
				<div className="load-more">
					<IconButton className="button" onClick={handleLoadMoreReviews}>
						<KeyboardArrowDownIcon />
					</IconButton>
				</div>
lfr20's avatar
lfr20 committed
			</ComentariosBox>
	function handleSuccessGet(data, headers) {
        if (currPageReviews !== 0)
            setReviews((previousState) => previousState.concat(data));
        else
            setReviews(data);
lfr20's avatar
lfr20 committed
		if (headers.has('X-Total-Count'))
			setTotalReviews(headers.get('X-Total-Count'))
		setIsLoading(false);
	}

	function handleFailGet(error) {
lfr20's avatar
lfr20 committed
		setIsLoading(false)
	useEffect(() => {
lfr20's avatar
lfr20 committed
		setIsLoading(true)
		getRequest(
lfr20's avatar
lfr20 committed
			`/collections/${props.id}/reviews?page=${currPageReviews}`,
			handleSuccessGet,
			(error) => { handleFailGet(error) }
		)
lfr20's avatar
lfr20 committed
	}, [render_state, currPageReviews]);
Raul Almeida's avatar
Raul Almeida committed

Raul Almeida's avatar
Raul Almeida committed
	return (
lfr20's avatar
lfr20 committed
		<CommentAreaContainer contrast={props.contrast} container xs={12} direction="row" justify="center" alignItems="center">
lfr20's avatar
lfr20 committed
			<SnackBarComponent
				snackbarOpen={snackInfo.open}
				handleClose={handleCloseSnack}
				severity={snackInfo.severity}
				text={snackInfo.text}
				color={snackInfo.color}
			/>
			<SignUpModal
vgm18's avatar
vgm18 committed
                contrast={props.contrast}
lfr20's avatar
lfr20 committed
				open={sign_up_open}
				handleClose={() => setSignUpOpen(false)}
				openLogin={() => setLoginOpen(true)}
			/>
			<LoginModal
vgm18's avatar
vgm18 committed
                contrast={props.contrast}
lfr20's avatar
lfr20 committed
				openSnackbar={handleOpenSnackSignIn}
				open={log_in_open}
				handleClose={() => setLoginOpen(false)}
				openSignUp={handleOpenSignUp}
			/>
Raul Almeida's avatar
Raul Almeida committed
			<Grid item xs={12} ref={comment_ref}>
lfr20's avatar
lfr20 committed
				<CommentAreaCard contrast={props.contrast}>
lfr20's avatar
lfr20 committed
					{
						props.currentUserId ?
							<Fragment>
lfr20's avatar
lfr20 committed
								<Title contrast={props.contrast}>Conte sua experiência com a coleção</Title>
lfr20's avatar
lfr20 committed
								<Grid container style={{ paddingTop: "20px" }} spacing={1}>
									<Grid item xs={12} sm={2} style={{ paddingLeft: "15px", paddingRight: "15px" }}>
										<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
											<Avatar src={props.avatar} alt="user avatar" />
lfr20's avatar
lfr20 committed
										</div>
									</Grid>
									<Grid item xs={12} sm={10}>
										<CommentForm
lfr20's avatar
lfr20 committed
											contrast={props.contrast}
lfr20's avatar
lfr20 committed
											colecao
											recursoId={props.id}
											handleSnackbar={handlePostSnackbar}
											rerenderCallback={forceUpdate}
										/>
									</Grid>
								</Grid>
lfr20's avatar
lfr20 committed
							</Fragment>
							:
							<Grid item xs={12}>
lfr20's avatar
lfr20 committed
								<LogInToComment contrast={props.contrast}>
lfr20's avatar
lfr20 committed
									<span className="span-purple">Você precisa entrar para comentar</span>
lfr20's avatar
lfr20 committed
									<Button onClick={() => setSignUpOpen(true)} style={props.contrast === "" ? { textTransform: "uppercase", color: "#666", fontWeight: "700" } : { textTransform: "uppercase", color: "yellow", fontWeight: "700", textDecoration: "underline" }}>
lfr20's avatar
lfr20 committed
										<ExitToAppIcon />ENTRAR
                  </Button>
								</LogInToComment>
							</Grid>
					}
lfr20's avatar
lfr20 committed
					{
						is_loading ?
							<LoadingDiv>
								<CircularProgress className="loading" />
							</LoadingDiv>
							:
lfr20's avatar
lfr20 committed
							reviews.length ? CollectionComments(props.contrast) : NoCommentsMessage(props.contrast)
				</CommentAreaCard>
			</Grid>
			<Snackbar
				open={post_snack_open}
				autoHideDuration={6000}
				onClose={handlePostSnackbar}
lfr20's avatar
lfr20 committed
				anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
lfr20's avatar
lfr20 committed
				<Alert onClose={handlePostSnackbar} severity="info">
					Seu comentário foi publicado com sucesso!
        </Alert>
lfr20's avatar
lfr20 committed
			</Snackbar>
			<Snackbar
				open={delete_snack_open}
				autoHideDuration={6000}
				onClose={handleDeleteSnackbar}
lfr20's avatar
lfr20 committed
				anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
lfr20's avatar
lfr20 committed
				<Alert onClose={handleDeleteSnackbar} severity="info">
					Comentário deletado com sucesso.
        </Alert>
lfr20's avatar
lfr20 committed
			</Snackbar>
		</CommentAreaContainer>
Raul Almeida's avatar
Raul Almeida committed
	);
}
lfr20's avatar
lfr20 committed
const ComentariosBox = styled.div`
    display : flex;
    flex-direction : column;
    padding : 20px;
    width : 100%;

    h3 {
        font-family: 'Roboto Light','Roboto Regular',Roboto;
        font-weight: 300;
        font-style: normal;
lfr20's avatar
lfr20 committed
				color: ${props => props.contrast === "" ? "#666" : "white"};
lfr20's avatar
lfr20 committed
        font-size: 1.857em;
        margin: 15px 2%;
        text-align : flex-start;
    }

    .comentario-template {
        margin-top: 5px;
        padding : 20px 0;
        border-bottom : 1px solid #f4f4f4;
    }

		.load-more{
lfr20's avatar
lfr20 committed
			width: 100%;
			display: flex; 
			flex-direction: row;
			justify-content: center; 
			align-items: center;
		}
		
		.button{
			box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
		}
lfr20's avatar
lfr20 committed
`

const Avatar = styled.img`
	height: 60px;
  width: 60px;
  border-radius: 50%;
  margin-left: 2%;
  margin-top: 5%;
`

lfr20's avatar
lfr20 committed
const LoadingDiv = styled.div`
	margin: 1em; 
	display: flex; 
	justify-content: center; 
	align-items: center;
	.loading{
		color: #673ab7; 
		size: 24px; 
	}
`

lfr20's avatar
lfr20 committed
const LogInToComment = styled.div`
    display : flex;
    flex-direction : column;
    text-align : center;
    padding : 20px;
    align-items : center;

    .span-purple {
        font-size : 24px;
        font-weight : 700;
        padding-bottom : 5px;
lfr20's avatar
lfr20 committed
				color: ${props => props.contrast === "" ? "#673ab7" : "white"};
lfr20's avatar
lfr20 committed
    }

    img {
        object-fit : contain !important;
        background-color : transparent !important;
    }
`
lfr20's avatar
lfr20 committed
const CommentAreaContainer = styled(Grid)`
lfr20's avatar
lfr20 committed
	padding: 10px;
lfr20's avatar
lfr20 committed
	background: ${props => props.contrast === "" ? "#f4f4f4" : "black"};
lfr20's avatar
lfr20 committed
const CommentAreaCard = styled(Card)`
	padding: 45px;
lfr20's avatar
lfr20 committed
	background: ${props => props.contrast === "" ? "#f4f4f4" : "black !important"};
	border: ${props => props.contrast === "" ? "" : "1px solid white!important"};
lfr20's avatar
lfr20 committed
const Title = styled.h1`
lfr20's avatar
lfr20 committed
	text-align: center;
	font-weight: 100;
lfr20's avatar
lfr20 committed
	color: ${props => props.contrast === "" ? "#666" : "white"};