Spaces:
Sleeping
Sleeping
import { | |
Select, | |
SelectContent, | |
SelectItem, | |
SelectTrigger, | |
SelectValue, | |
} from "@/components/ui/select" | |
import { ChevronLeft, Menu } from "lucide-react" | |
import { useEffect, useState } from "react"; | |
import { ToastContainer, toast } from "react-toastify" | |
import 'react-toastify/dist/ReactToastify.css'; | |
function App() { | |
const [subject, setSubject] = useState(""); | |
const [difficultie, setDifficultie] = useState(""); | |
const [menuState, setMenuState] = useState(true); | |
const [isLoading, setIsLoading] = useState(false); | |
const [questions, setQuestions] = useState(null); | |
const [selectedMatter, setSelectedMatter] = useState("biologia"); | |
const matter = [ | |
{ label: "Biologia", value: "biologia" }, | |
{ label: "História", value: "historia" }, | |
]; | |
const biologySubjects = [ | |
{ label: "Fisiologia", value: "fisiologia" }, | |
{ label: "Embriologia", value: "embriologia" }, | |
{ label: "Citologia", value: "citologia" }, | |
{ label: "Genética", value: "genetica" }, | |
{ label: "Botânica", value: "botanica" }, | |
{ label: "Zoologia", value: "zoologia" }, | |
{ label: "Morfologia", value: "morfologia" }, | |
{ label: "Ecologia", value: "ecologia" }, | |
{ label: "Biofísica", value: "biofisica" }, | |
] | |
const historySubjects = [ | |
{ label: "Revoluções", value: "revoluções" }, | |
{ label: "Grécia", value: "grécia" }, | |
{ label: "Roma", value: "roma" }, | |
{ label: "Primeira Guerra Mundial", value: "primeira guerra mundial" }, | |
{ label: "Guerra Fria", value: "guerra fria" }, | |
{ label: "Feudalismo", value: "feudalismo" }, | |
] | |
const difficulties = [ | |
{ label: "Fácil", value: "facil" }, | |
{ label: "Intermediária", value: "intermediaria" }, | |
{ label: "Difícil", value: "dificil" }, | |
] | |
const handleSubmit = async (e) => { | |
e.preventDefault(); | |
setIsLoading(true); | |
try { | |
const res = await fetch("/generate_questions", { | |
method: "POST", | |
headers: { | |
"Content-Type": "application/json" | |
}, | |
body: JSON.stringify({ | |
matter: selectedMatter, | |
subject, difficultie | |
}) | |
}); | |
if (res.ok) { | |
const data = await res.json(); | |
setQuestions(data.rag_result.questions); | |
} else { | |
toast.error("Erro ao gerar questões", { | |
position: "top-right", | |
autoClose: 5000, | |
hideProgressBar: false, | |
closeOnClick: true, | |
pauseOnHover: true, | |
draggable: true, | |
progress: undefined, | |
className: "bg-slate-900 text-white font-semibold", | |
}); | |
} | |
} catch (err) { | |
console.error(err); | |
toast.error("Erro ao gerar questões", { | |
position: "top-right", | |
autoClose: 5000, | |
hideProgressBar: false, | |
closeOnClick: true, | |
pauseOnHover: true, | |
draggable: true, | |
progress: undefined, | |
className: "bg-slate-900 text-white font-semibold", | |
}); | |
} | |
setIsLoading(false); | |
} | |
useEffect(() => { | |
const handleResize = () => { | |
if (window.innerWidth > 768) { | |
setMenuState(true); | |
} else { | |
setMenuState(false); | |
} | |
} | |
window.addEventListener("resize", handleResize); | |
return () => window.removeEventListener("resize", handleResize); | |
} | |
, []); | |
return ( | |
<div className="font-sans h-screen text-white min-h-screen bg-slate-900 flex flex-col relative overflow-hidden"> | |
<header className="p-10 flex items-center gap-2.5"> | |
<Menu className="md:hidden" onClick={() => setMenuState(prev => !prev)} /> | |
<h1 className="text-3xl font-bold"> | |
Pergunt.<span className="text-transparent bg-clip-text bg-gradient-to-r from-green-300 to bg-blue-500">AÍ</span> | |
</h1> | |
</header> | |
<main className="flex-1 flex overflow-hidden"> | |
{ | |
menuState && | |
<form | |
onSubmit={handleSubmit} | |
className="p-10 flex flex-col gap-2.5 absolute top-0 bg-black/95 h-full z-10 md:static md:h-full md:bg-transparent"> | |
<div className="md:sr-only"> | |
<ChevronLeft className="w-10 h-10" onClick={e => setMenuState(prev => !prev)} /> | |
</div> | |
<h2>Selecione uma matéria:</h2> | |
<Select defaultValue="biologia" onValueChange={value => setSelectedMatter(value)}> | |
<SelectTrigger className="w-[180px]"> | |
<SelectValue placeholder="Matéria" /> | |
</SelectTrigger> | |
<SelectContent > | |
{ | |
matter.map(({ label, value }) => ( | |
<SelectItem key={value} value={value}>{label}</SelectItem> | |
)) | |
} | |
</SelectContent> | |
</Select> | |
<h2>Selecione um conteúdo:</h2> | |
<Select onValueChange={value => setSubject(value)}> | |
<SelectTrigger className="w-[180px]"> | |
<SelectValue placeholder="Conteúdo" /> | |
</SelectTrigger> | |
<SelectContent onChange={e => console.log(e)}> | |
{ | |
selectedMatter === "biologia" ? | |
biologySubjects.map(({ label, value }) => ( | |
<SelectItem key={value} value={value}>{label}</SelectItem> | |
)) | |
: | |
historySubjects.map(({ label, value }) => ( | |
<SelectItem key={value} value={value}>{label}</SelectItem> | |
)) | |
} | |
</SelectContent> | |
</Select> | |
<h2>Selecione uma dificuldade:</h2> | |
<Select onValueChange={value => setDifficultie(value)}> | |
<SelectTrigger className="w-[180px]"> | |
<SelectValue placeholder="Dificuldade" /> | |
</SelectTrigger> | |
<SelectContent onChange={e => console.log(e)}> | |
{difficulties && difficulties.map(({ label, value }) => ( | |
<SelectItem key={value} value={value}>{label}</SelectItem> | |
))} | |
</SelectContent> | |
</Select> | |
<button className="h-10 bg-purple-500 rounded px-2.5 py-1 mt-5 hover:brightness-110 transition-all flex items-center justify-center disabled:hover:brightness-75 disabled:brightness-75" | |
disabled={isLoading || !subject || !difficultie}> | |
{ | |
isLoading ? | |
<div className="animate-spin h-5 w-5 border-2 border-white border-r-purple-500 rounded-full"></div> | |
: | |
"Enviar" | |
} | |
</button> | |
</form> | |
} | |
<section className="p-10 flex-1 md:border-l-2 md:border-l-white flex flex-col gap-2.5 "> | |
<h2 className="text-2xl font-bold">Questões</h2> | |
<div className="w-full h-full flex flex-col gap-5 rounded p-2.5 overflow-y-scroll"> | |
{questions ? | |
questions.map(({ question, options, answer }, index) => ( | |
<div key={index} className="bg-slate-950 ring-2 ring-white p-2.5 rounded"> | |
{question}<br /><br /> | |
{options.map((option, i) => ( | |
<div key={i}> | |
{option} | |
</div> | |
))}<br /> | |
Resposta correta: {answer} | |
</div> | |
)) | |
: <div className="p-2.5 bg-slate-950 ring-2 ring-white rounded">{"Ainda sem questões"}</div>} | |
</div> | |
</section> | |
<ToastContainer /> | |
</main> | |
</div> | |
) | |
} | |
export default App | |