diff --git a/src/app/editar/[id]/page.js b/src/app/editar/[id]/page.js index bc5c10d908619c45a1c9d5f226d2332ce2ecba0c..60937ba8379cf278968ae0f449a11e847ac6e939 100644 --- a/src/app/editar/[id]/page.js +++ b/src/app/editar/[id]/page.js @@ -28,14 +28,13 @@ export default function Edit({ params }) { } }) .then(({ data }) => { - console.log("aaa", userData) setUserData(data); }) .catch((error) => console.error(error)) } fetchUser(params.id) - }, [params.id, token, client, uid]) + }, [params.id, token, client, uid, loginBarrier]) const ErrorEdit = () => { return ( diff --git a/src/app/entrar/components/LoginForm.js b/src/app/entrar/components/LoginForm.js index 7fcf6bce3649f2bd24d860eae3da80852f823ca5..4d13d8cecd293bf86053d261c6f1f1b03d22f1e6 100644 --- a/src/app/entrar/components/LoginForm.js +++ b/src/app/entrar/components/LoginForm.js @@ -126,7 +126,7 @@ export default function LoginForm({ variant="outlined" className="mt-2 bg-white border-white text-main-text normal-case flex gap-2 w-96 hover:bg-main-hover" > - <Image className="w-6 h-6" src="/google.svg" width={10} height={10} /> + <Image className="w-6 h-6" src="/google.svg" width={10} height={10} alt="Google" /> <span>Entrar com o Google</span> </Button> <SignupModal open={openModalSignup} handleClose={handleCloseModalSignup} /> diff --git a/src/app/perfil/[id]/components/CardsHomologation.js b/src/app/perfil/[id]/components/CardsHomologation.js index 11026e6b8667ca9c19f5021aff1da4b221b85d19..03eef4e37cfe6d163f87207fde99bb570a802027 100644 --- a/src/app/perfil/[id]/components/CardsHomologation.js +++ b/src/app/perfil/[id]/components/CardsHomologation.js @@ -4,6 +4,7 @@ import CardMedia from "@mui/material/CardMedia"; import Avatar from "@mui/material/Avatar"; import Typography from "@mui/material/Typography"; import Link from "next/link"; +import { useRouter } from "next/navigation"; const getDefaultThumbnail = (type) => { let thumbnail_url; @@ -50,6 +51,9 @@ const getDefaultThumbnail = (type) => { * @returns Cards de recursos para homologação */ export default function CardsHomologation({ item, key }) { + const router = useRouter() + console.log(item) + return ( <Card className="transition items-center mt-5 mx-2 min-h-[320px]" @@ -116,6 +120,7 @@ export default function CardsHomologation({ item, key }) { <div className="flex items-end"> <Button variant="outlined" className=" " alt='Avaliar' + onClick={() => router.push(`/recurso/${item["learning_object"]["id"]}`)} > Avaliar </Button> diff --git a/src/app/perfil/[id]/components/GroupButton.js b/src/app/perfil/[id]/components/GroupButton.js index d564d184ae2609bf66d47930ee78eb83f6b57283..d3f85abc1340dc986b7a36d2deec947ea59c2373 100644 --- a/src/app/perfil/[id]/components/GroupButton.js +++ b/src/app/perfil/[id]/components/GroupButton.js @@ -136,7 +136,7 @@ export default function GroupButton({ profileData, idLogin }) { onClick={() => { if (!loginBarrier()) return; - if (profileData.complained){ + if (complained){ setReported(true) return; } diff --git a/src/app/recurso/[id]/components/actionButtons.js b/src/app/recurso/[id]/components/actionButtons.js index 2328ea8b3428b09503e53f545c472b77ac47cb83..68ed7d3f36332e42998f332bed9b359b8e26aa91 100644 --- a/src/app/recurso/[id]/components/actionButtons.js +++ b/src/app/recurso/[id]/components/actionButtons.js @@ -14,6 +14,7 @@ import { useState, useEffect } from "react"; import ShareModal from "../../../components/ShareModal"; import ReportModal from "./reportModal"; import CollectModal from "./collectModal"; +import HomologationModal from "./homologationModal"; function ChangeOnHover({ text, textOnHover }) { return ( @@ -24,7 +25,7 @@ function ChangeOnHover({ text, textOnHover }) { ); } -export default function ActionButtons({ learningObject, setNeedLoginOpen }) { +export default function ActionButtons({ learningObject, setNeedLoginOpen, state }) { const [liked, setLiked] = useState(learningObject.liked); const [shareOpen, setShareOpen] = useState(false); @@ -32,6 +33,8 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen }) { const [reported, setReported] = useState(false); const [collectOpen, setCollectOpen] = useState(false) const [userData, setUserData] = useState(""); + const [submitOpen, setSubmitOpen] = useState(false) + const [submitted, setSubmitted] = useState(state === "submitted" ? true : false) const token = getStoredValue("access_token"); const client = getStoredValue("client"); @@ -185,6 +188,7 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen }) { return ( <> + <HomologationModal open={submitOpen} onClose={() => setSubmitOpen(false)} name={learningObject.name} id={learningObject.submission_id} setSubmitted={setSubmitted}/> <ShareModal open={shareOpen} onClose={() => setShareOpen(false)} /> <ReportModal learningObject={learningObject} @@ -193,9 +197,17 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen }) { /> {/* Verifica se o usuário está logado antes de abrir o modal de colecionar */} {userData && <CollectModal open={collectOpen} onClose={() => setCollectOpen(false)} idLogin={userData["id"]} resourceId={learningObject.id} />} - <div className="flex justify-start py-4 flex-wrap overflow-x-auto"> - {buttonInfo.map(genButton)} - </div> + {state !== "submitted" && + <div className="flex justify-start py-4 flex-wrap overflow-x-auto"> + {buttonInfo.map(genButton)} + </div> + } + { + submitted && + <div className="flex justify-end pb-2 mt-2"> + <button onClick={() => setSubmitOpen(true)} className="bg-orange p-2 text-white font-semi-bold rounded-lg hover:bg-orange-hover">Avaliar Submissão</button> + </div> + } </> ); } diff --git a/src/app/recurso/[id]/components/homologationModal.js b/src/app/recurso/[id]/components/homologationModal.js new file mode 100644 index 0000000000000000000000000000000000000000..370f66ca3dd5aa35f27d0c54b62b8d96b4c84dd8 --- /dev/null +++ b/src/app/recurso/[id]/components/homologationModal.js @@ -0,0 +1,161 @@ +import { getStoredValue } from "@/app/handlers/localStorageHandler"; +import mecredApi from "@/axiosConfig"; +import { FormControlLabel, Modal, Radio, RadioGroup, TextField } from "@mui/material"; +import { useEffect, useState } from "react"; + +export default function HomologationModal({ open, onClose, name, id, setSubmitted }) { + const [questions, setQuestions] = useState([]) + const [payload, setPayload] = useState([]) + const [justification, setJustification] = useState("") + const [confirmOpen, setConfirmOpen] = useState(false) + const [notSucess, setNotSucess] = useState(false) + const token = getStoredValue("access_token"); + const client = getStoredValue("client"); + const uid = getStoredValue("uid"); + let count = 0 + + useEffect(() => { + const fetchQuestions = async () => { + mecredApi.get("/questions") + .then((response) => { + setQuestions(response.data) + }) + } + fetchQuestions() + }, []) + + const handleJustification = (e) => { + setJustification(e.target.value) + } + + const handleRadios = (e, id) => { + const obj = { question_id: id, accepted: e.target.value === "Sim" ? false : true } + setPayload((prev) => { + const index = prev.findIndex(item => item.question_id === id) + if (index !== -1) { + return prev.map((item) => item.question_id === id ? obj : item) + } else { + count++ + return [...prev, obj] + } + }) + } + + const handleSubmit = (e) => { + e.preventDefault() + + payload.sort((a, b) => a.question_id - b.question_id) + + let payloadSub = { + "submission": { + "justification": justification, + "answers": payload + } + } + let headers = { + headers: { + "access-token": token, + "token-type": "Bearer", + client: client, + uid: uid, + Expires: 0, + } + } + + // submission_id + mecredApi.post(`/submissions/${id}/answer`, payloadSub, headers) + setSubmitted(false) + setConfirmOpen(false) + onClose() + + } + + const ConfirmModal = ({ open, onClose }) => { + return ( + + <Modal + open={open} + onClose={onClose} + className="grid h-screen place-items-center mx-5" + > + <div className="flex flex-col bg-main p-5 rounded-lg "> + <p className="flex justify-center text-main-text font-bold text-2xl">Recurso a ser aprovado</p> + <p className="pt-3 text-lg text-main-text ">Este recurso será publicado na plataforma. Você confirma essa avaliação?</p> + <div className="flex flex-row justify-end pt-5"> + + <button onClick={() => onClose()} className="bg-main px-3 py-2 mr-1 rounded-lg text-main-text hover:bg-main-hover">Alterar avaliação</button> + <button onClick={handleSubmit} className="bg-secondary px-3 py-2 ml-1 rounded-lg text-white font-semibold hover:bg-secondary-hover">Confirmar</button> + </div> + </div> + + + </Modal> + ) + } + + const NotSucessModal = ({ open, onClose }) => { + return ( + + <Modal + open={open} + onClose={onClose} + className="grid h-screen place-items-center mx-5" + > + <div className="flex flex-col bg-main p-5 rounded-lg "> + <p className="pt-3 text-lg text-main-text ">É necessário que todas perguntas sejam respondidas.</p> + <div className="flex flex-row justify-end pt-5"> + <button onClick={() => onClose()} className="bg-main px-3 py-2 mr-1 rounded-lg text-main-text hover:bg-main-hover">Ok</button> + </div> + </div> + + + </Modal> + ) + } + + + return ( + + <> + <Modal + open={open} + onClose={onClose} + className="grid h-screen place-items-center mx-5" + > + <div className="flex flex-col bg-main p-5 rounded-lg"> + <ConfirmModal open={confirmOpen} onClose={() => { setConfirmOpen(false) }} /> + <NotSucessModal open={notSucess} onClose={() => { setNotSucess(false) }} /> + <p className="flex justify-center text-2xl text-main-text font-bold pb-2">{`Você está avaliando a submissão ${name}`}</p> + <p className="text-main-text pb-4 pt-4 text-lg font-semibold">Esse recurso está em conformidade com os critérios? Marque as opções e justifique aquela(s) que não estiverem em conformidade.</p> + {questions.map((item, i) => { + return ( + <div key={i} className="pb-4"> + <p className="text-main-text text-lg" key={i}>{item.description}</p> + <RadioGroup row onChange={(e) => { handleRadios(e, item.id) }}> + <FormControlLabel value={"Não"} control={<Radio />} label="Não" className="text-main-text" /> + <FormControlLabel value={"Sim"} control={<Radio />} label="Sim" className="text-main-text" /> + </RadioGroup> + </div> + ) + })} + {/* */} + + <TextField + className="" + id="justificativa" + name="justificativa" + onChange={handleJustification} + maxRows={5} + multiline + label="Justificativa (opcional)" + variant="standard" + /> + <div className="flex justify-end mt-5"> + <button onClick={onClose} className="bg-main px-3 py-2 mr-1 rounded-lg text-main-text hover:bg-main-hover">Cancelar</button> + <button onClick={() => { payload.length < 4 ? setNotSucess(true) : setConfirmOpen(true) }} className="bg-secondary px-3 py-2 ml-1 rounded-lg text-white font-semibold hover:bg-secondary-hover">Enviar</button> + </div> + </div> + </Modal> + </> + ) +} \ No newline at end of file diff --git a/src/app/recurso/[id]/page.js b/src/app/recurso/[id]/page.js index 1999ef741a8deb9826028860764acf776216a0e0..766ccf83ad1454499431c39ab8d3e938ea537b39 100644 --- a/src/app/recurso/[id]/page.js +++ b/src/app/recurso/[id]/page.js @@ -6,18 +6,21 @@ import PublisherInfo from "./components/publisherInfo"; import Overlay from "../../components/Overlay"; import ResourceInfo from "./components/resourceInfo"; import RelatedResources from "./components/relatedResources"; -import { isLoggedIn} from "@/app/handlers/loginHandler"; +import { isLoggedIn } from "@/app/handlers/loginHandler"; import mecredApi from "@/axiosConfig"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; import Loading from "@/app/components/Loading"; import ResourcePreview from "./components/resourcePreview"; import NeedLoginModal from "./components/needLoginModal"; import ErrorComponent from "@/app/components/ErrorComponent"; +import HomologationModal from "./components/homologationModal"; export default function Recurso({ params }) { const [learningObject, setLearningObject] = useState(undefined); const [needLoginOpen, setNeedLoginOpen] = useState(false); const [error, setError] = useState(false) + const [state, setState] = useState() + const [submitOpen, setSubmitOpen] = useState(false) const token = getStoredValue("access_token"); const client = getStoredValue("client"); @@ -42,38 +45,51 @@ export default function Recurso({ params }) { }) .then((response) => { setLearningObject(response.data); + setState(response.data.state === "submitted" ? true : false) }) - .catch(() => {setError(true);}) + .catch(() => { setError(true); }) }, [params.id, client, token, uid]); return ( <> <Overlay> - {!learningObject ? ( error ? + {!learningObject ? (error ? <ErrorComponent name="Recurso" /> : - + <Loading scroll /> ) : ( <> - <NeedLoginModal open={needLoginOpen} setOpen={setNeedLoginOpen}/> + <HomologationModal open={submitOpen} onClose={() => setSubmitOpen(false)} name={learningObject.name} id={learningObject.submission_id} setSubmitted={setState} /> + + <NeedLoginModal open={needLoginOpen} setOpen={setNeedLoginOpen} /> <div className="flex flex-col lg:flex-row"> <div className="flex flex-col bg-main p-3 lg:w-[55%] flex-shrink-0"> <div className=" flex justify-center"> {/* Pré-visualização */} <ResourcePreview learningObject={learningObject} /> </div> - <div className="text-main-text mt-5 text-2xl font-bold"> - {/* Título */} - <h1>{learningObject.name}</h1> - </div> - <div className="text-main-text mt-3 text-sm font-bold"> - {/* tags */} - <Tags tags={learningObject.tags} /> + <div className="flex flex-row justify-between"> + <div className="flex flex-col"> + + <div className="text-main-text mt-5 text-2xl font-bold"> + {/* Título */} + <h1>{learningObject.name}</h1> + </div> + <div className="text-main-text text-sm font-bold"> + {/* tags */} + <Tags tags={learningObject.tags} /> + </div> + </div> + {state && + <div className=" flex items-center mt-5"> + <button onClick={() => setSubmitOpen(true)} className="bg-orange p-2 text-white font-semi-bold rounded-lg hover:bg-orange-hover">Avaliar Submissão</button> + </div> + } </div> <div className=""> {/* Modal de entrar */} - <ActionButtons learningObject={learningObject} setNeedLoginOpen={setNeedLoginOpen} /> + <ActionButtons learningObject={learningObject} setNeedLoginOpen={setNeedLoginOpen} state={state} /> </div> <div className=""> {/* Publicador */}