From cbc80198f24da2430f1ea7ce1e048961d6b8f08a Mon Sep 17 00:00:00 2001 From: Luis Felipe Risch <lfr20@inf.ufpr.br> Date: Fri, 26 Feb 2021 12:06:39 -0300 Subject: [PATCH] Finish to build aprove teacher List --- .../Pages/Pages/SubPages/AproveTeacher.js | 612 ++++++++++++++++++ 1 file changed, 612 insertions(+) create mode 100644 src/Admin/Pages/Pages/SubPages/AproveTeacher.js diff --git a/src/Admin/Pages/Pages/SubPages/AproveTeacher.js b/src/Admin/Pages/Pages/SubPages/AproveTeacher.js new file mode 100644 index 00000000..22747f11 --- /dev/null +++ b/src/Admin/Pages/Pages/SubPages/AproveTeacher.js @@ -0,0 +1,612 @@ +/*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, { useEffect, useState, useContext } from "react"; +import moment from "moment"; +//imports from local files +import TableData from "../../../Components/Components/Table"; +import SnackBar from "../../../../Components/SnackbarComponent"; +import { Url } from "../../../Filters"; +import { Store } from "../../../../Store"; +import LoadingSpinner from "../../../../Components/LoadingSpinner"; +import { getRequest, postRequest } from "../../../../Components/HelperFunctions/getAxiosConfig"; +//imports from material ui +import { withStyles } from "@material-ui/core/styles"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import MenuItem from "@material-ui/core/MenuItem"; +import TableRow from "@material-ui/core/TableRow"; +import TextField from "@material-ui/core/TextField"; +import IconButton from "@material-ui/core/IconButton"; +import { Button, Typography, Paper, Grid } from "@material-ui/core"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import AddRoundedIcon from "@material-ui/icons/AddRounded"; +import UpdateRoundedIcon from "@material-ui/icons/UpdateRounded"; +import FilterListRoundedIcon from "@material-ui/icons/FilterListRounded"; +import VisibilityIcon from "@material-ui/icons/Visibility"; +import CheckRoundedIcon from "@material-ui/icons/CheckRounded"; +import CloseRoundedIcon from "@material-ui/icons/CloseRounded"; +//routers +import { Link } from "react-router-dom"; +import Unauthorized from "../../../Components/Components/Unauthorized"; + +let currPage = 0; +let currContentState = "requested"; +let currContentName = ""; +let currContentEmail = ""; + +const StyledTableCell = withStyles((theme) => ({ + head: { + backgroundColor: theme.palette.common.black, + color: theme.palette.common.white, + }, + body: { + fontSize: 14, + }, +}))(TableCell); + +const StyledTableRow = withStyles((theme) => ({ + root: { + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, + }, + }, +}))(TableRow); + +const AproveTeacher = () => { + const { state, dispatch } = useContext(Store); + + const ADD_ONE_LENGHT = [""]; + const TOP_LABELS = [ + "ESTADO DO PEDIDO", + "ID", + "NOME", + "EMAIL", + "PEDIDO EM(MM/DD/YYYY)", + "VISUALIZAR", + "AÇÕES", + ]; //Labels from Table + + const [error, setError] = useState(null); //Necessary to consult the API, catch errors + const [isLoaded, setIsLoaded] = useState(false); //Necessary to consult the API, wait until complete + const [items, setItems] = useState([]); //Necessary to consult the API, data + + const [isLoadingMoreItems, setIsLoadingMoreItems] = useState(false); //controlls the state of loadind more data + const [isUpdating, setIsUpdating] = useState(false); //controlls the state of updating data + + const [showFilter, setShowFilter] = useState(false); + + const [option, setOption] = useState("Pendente"); + const [name, setName] = useState(""); + const [email, setEmail] = useState(""); + + const [snackInfo, setSnackInfo] = useState({ + message: "", + icon: "", + open: false, + color: "", + }); + + const StateOptions = [ + { id: "requested", name: "Pendente" }, + { id: "accepted", name: "Aceito" }, + { id: "rejected", name: "Rejeitado" }, + ]; + + //handle snack info + const HandleSnack = (message, state, icon, color) => { + setSnackInfo({ + message: message, + icon: icon, + open: state, + color: color, + }); + }; + + const CheckUserPermission = () => { + let canUserEdit = false; + + if (state.userIsLoggedIn) { + const roles = [...state.currentUser.roles]; + for (let i = 0; i < roles.length; i++) + if (roles[i].name === "admin" || roles[i].name === "editor") + canUserEdit = true; + } else { + canUserEdit = false; + } + + return canUserEdit; + }; + + //handle load more items + const LoadMoreItens = async (api) => { + setIsLoadingMoreItems(true); + getRequest( + api, + (data, header) => { + const arrData = [...data]; + if (arrData.length === 0) { + HandleSnack( + "Não há mais dados para serem carregados", + true, + "warning", + "#FFC125" + ); + } else { + const arrItems = [...items]; + arrItems.pop(); //Deleting the last position, that was used to display the button of load more items + const arrResult = arrItems.concat(arrData); + setItems(arrResult.concat(ADD_ONE_LENGHT)); + } + setIsLoadingMoreItems(false); + }, + (error) => { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + setIsLoadingMoreItems(false); + } + ); + }; + + // handle update list data + const UpdateHandler = async (api) => { + setIsUpdating(true); + getRequest( + api, + (data, header) => { + HandleSnack( + "A lista de dados foi atualizada", + true, + "success", + "#228B22" + ); + const arrData = [...data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + setIsUpdating(false); + }, + (error) => { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + setIsUpdating(false); + } + ); + }; + + const handleChange = (e, type) => { + const value = e.target.value; + console.log(e); + setOption(value); + }; + + const ApplyFilter = (id, type) => { + currPage = 0; + currContentState = id; + getRequest( + Url( + "users", + `"submitter_request":"${currContentState}","name":"${currContentName}","email":"${currContentEmail}"`, + `${currPage}`, + "DESC" + ), + (data, header) => { + const arrData = [...data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); + setIsLoaded(true); + }, + (error) => { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + setIsLoaded(true); + } + ); + }; + + const NameHandler = (e) => { + currPage = 0; + currContentName = e.target.value; + getRequest( + Url( + "users", + `"submitter_request":"${currContentState}","name":"${currContentName}","email":"${currContentEmail}"`, + `${currPage}`, + "DESC" + ), + (data, header) => { + const arrData = [...data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); + setIsLoaded(true); + }, + (error) => { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + setIsLoaded(true); + } + ); + }; + + const EmailHandler = (e) => { + currPage = 0; + currContentEmail = e.target.value; + getRequest( + Url( + "users", + `"submitter_request":"${currContentState}","name":"${currContentName}","email":"${currContentEmail}"`, + `${currPage}`, + "DESC" + ), + (data, header) => { + const arrData = [...data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + HandleSnack("Filtro aplicado com sucesso", true, "success", "#228B22"); + setIsLoaded(true); + }, + (error) => { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + setIsLoaded(true); + } + ); + }; + + const ComplaintStatus = (status) => { + switch (status) { + case "accepted": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#228B22", + fontWeight: "500", + color: "#FFFAFA", + }} + > + ACEITO + </Paper> + ); + case "requested": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#FF8C00", + fontWeight: "500", + color: "#FFFAFA", + }} + > + PENDENTE + </Paper> + ); + case "rejected": + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#FA8072", + fontWeight: "500", + color: "#FFFAFA", + }} + > + Rejeitado + </Paper> + ); + default: + return ( + <Paper + style={{ + textAlign: "center", + padding: "0.5em", + backgroundColor: "#797D7F ", + fontWeight: "500", + color: "#FFFAFA", + }} + > + Não requisitado + </Paper> + ) + } + }; + + const DisplayDate = (date) => { + const convertedData = moment.utc(date); + return moment(convertedData) + .format("LLL") + .toString(); + }; + + const handleAprove = (userId, userName) => { + const url = `/users/${userId}/add_teacher` + const body = { + "approves" : true + } + postRequest( + url, + body, + (data) => { + HandleSnack(`${userName} aceito como professor!`, true, "success", "#228B22"); + }, + (error) => { + HandleSnack("Erro!", true, "warning", "#FA8072"); + } + ) + } + + const handleReject = (userId, userName) => { + const url = `/users/${userId}/add_teacher` + const body = { + "user" : { + "approves" : false + } + } + postRequest( + url, + body, + (data) => { + HandleSnack(`${userName} rejeitado como professor!`, true, "success", "#228B22"); + }, + (error) => { + HandleSnack("Erro!", true, "warning", "#FA8072"); + } + ) + } + + //getting data from server + useEffect(() => { + getRequest( + Url( + "users", + `"submitter_request":"${currContentState}","name":"${currContentName}","email":"${currContentEmail}"`, + `${currPage}`, + "DESC" + ), + (data, header) => { + const arrData = [...data]; + setItems(arrData.concat(ADD_ONE_LENGHT)); + setIsLoaded(true); + setError(false); + }, + (error) => { + HandleSnack("Erro ao carregar os dados", true, "warning", "#FA8072"); + setIsLoaded(true); + setError(true); + } + ); + }, []); + + if (error) { + return <div>Error: {error.message}</div>; + } else if (!isLoaded) { + return <LoadingSpinner text="Carregando..." />; + } else if (CheckUserPermission()) { + return ( + <> + <SnackBar + severity={snackInfo.icon} + text={snackInfo.message} + snackbarOpen={snackInfo.open} + color={snackInfo.color} + handleClose={() => + setSnackInfo({ + message: "", + icon: "", + open: false, + color: "", + }) + } + /> + + <Paper style={{ padding: "1em" }}> + <Grid container spacing={3} direction="row" alignItems="center"> + <Grid item xs={6}> + <Typography variant="h4"> + Lista de pedidos para professores + </Typography> + </Grid> + + <Grid item xs={6}> + <Grid container justify="flex-end" spacing={3}> + <Grid item> + <Button + variant="contained" + color="secondary" + disabled={isUpdating} + onClick={() => { + currPage = 0; + UpdateHandler( + Url( + "users", + `"submitter_request":"${currContentState}","name":"${currContentName}","email":"${currContentEmail}"`, + `${currPage}`, + "DESC" + ), + ); + }} + startIcon={<UpdateRoundedIcon />} + > + {isUpdating ? <CircularProgress size={24} /> : "Atualizar"} + </Button> + </Grid> + <Grid item> + <Button + variant="contained" + color="secondary" + onClick={() => { + currPage = 0; + UpdateHandler( + Url( + "users", + `"submitter_request":"${currContentState}","name":"${currContentName}","email":"${currContentEmail}"`, + `${currPage}`, + "DESC" + ), + ); + setShowFilter(!showFilter); + }} + startIcon={<FilterListRoundedIcon />} + > + Filtrar + </Button> + </Grid> + </Grid> + </Grid> + </Grid> + + {showFilter ? ( + <Grid + container + direction="row" + justify="space-between" + alignItems="center" + alignContent="flex-end" + spacing={3} + xs={12} + > + <Grid item> + <TextField + select + label="Estado" + value={option ? option : ""} + onChange={handleChange} + helperText="Por favor, selecione uma das opções" + > + {StateOptions.map((option, index) => ( + <MenuItem + key={option.id} + value={option.name} + name={option.id} + onClick={() => + ApplyFilter(option.id, "submitter_request") + } + > + {option.name} + </MenuItem> + ))} + </TextField> + </Grid> + <Grid item> + <TextField label="Nome" onBlur={NameHandler} value={name} onChange={(e) => {setName(e.target.value)}} /> + </Grid> + <Grid item> + <TextField label="Email" onBlur={EmailHandler} value={email} onChange={(e) => {setEmail(e.target.value)}} /> + </Grid> + </Grid> + ) : null} + </Paper> + + <div style={{ height: "2em" }}></div> + + <Grid xs={12} container> + <TableData top={TOP_LABELS}> + <TableBody> + {items.map((row, index) => + index === items.length - 1 ? ( + <StyledTableRow key={index}> + {/* Button to load more data */} + <StyledTableCell> + <Button + color="primary" + variant="text" + // disabled={isLoadingMoreItems} + startIcon={<AddRoundedIcon />} + disabled={isLoadingMoreItems} + onClick={() => { + currPage++; + LoadMoreItens( + Url( + "users", + `"submitter_request":"${currContentState}","name":"${currContentName}","email":"${currContentEmail}"`, + `${currPage}`, + "DESC" + ), + ) + }} + > + {isLoadingMoreItems ? ( + <CircularProgress size={24} /> + ) : ( + "Carregar mais itens" + )} + </Button> + </StyledTableCell> + </StyledTableRow> + ) : ( + <StyledTableRow + key={index} + style={{ flex: 1, width: "100%" }} + > + <StyledTableCell component="th" scope="row"> + {ComplaintStatus(row.submitter_request)} + </StyledTableCell> + <StyledTableCell align="right">{row.id}</StyledTableCell> + <StyledTableCell align="right">{row.name}</StyledTableCell> + <StyledTableCell align="right">{row.email}</StyledTableCell> + <StyledTableCell align="right"> + {DisplayDate(row.created_at)} + </StyledTableCell> + <StyledTableCell align="right"> + <Link to={`/admin/user/${row.id}`}> + <IconButton + onClick={() => { + currPage = 0; + }} + > + <VisibilityIcon style={{ fill: "#00bcd4" }} /> + </IconButton> + </Link> + </StyledTableCell> + <StyledTableCell align="right"> + <Button + variant="contained" + color="secondary" + style={{ width: "100%" }} + disabled={ + row.submitter_request === "requested" ? false : true + } + startIcon={ + <CloseRoundedIcon style={{ fill: "#FFFAFA" }} /> + } + onClick={() => {handleReject(row.id, row.name)}} + > + Recusar + </Button> + <div style={{ height: "0.5em" }} /> + <Button + variant="contained" + color="primary" + style={{ width: "100%" }} + disabled={ + row.submitter_request === "requested" ? false : true + } + startIcon={ + <CheckRoundedIcon style={{ fill: "#FFFAFA" }} /> + } + onClick={() => {handleAprove(row.id, row.name)}} + > + Aceitar + </Button> + </StyledTableCell> + </StyledTableRow> + ) + )} + </TableBody> + </TableData> + </Grid> + </> + ); + } else return <Unauthorized />; +}; +export default AproveTeacher; -- GitLab