Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 6 additions & 26 deletions eduaid_web/src/pages/Home.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,18 @@ import arrow from "../assets/arrow.png";
import gitStar from "../assets/gitStar.png";
import { FaGithub } from "react-icons/fa";
import { Link } from "react-router-dom";
import { getCachedGithubStars } from "../utils/githubStars";

const Home = () => {
const [stars, setStars] = useState(null);
const [error, setError] = useState("");

async function fetchGitHubStars() {
const response = await fetch("https://api.github.com/repos/AOSSIE-Org/EduAid");
if (!response.ok) throw new Error("Failed to fetch stars");
const data = await response.json();
return data.stargazers_count;
}

function isMoreThanOneDayOld(timestamp) {
const oneDay = 24 * 60 * 60 * 1000;
return Date.now() - timestamp > oneDay;
}

useEffect(() => {
const storedStars = localStorage.getItem("stars");
const storedTime = localStorage.getItem("fetchTime");

if (storedStars && storedTime && !isMoreThanOneDayOld(parseInt(storedTime))) {
setStars(parseInt(storedStars));
} else {
fetchGitHubStars()
.then((starCount) => {
setStars(starCount);
localStorage.setItem("stars", starCount);
localStorage.setItem("fetchTime", Date.now().toString());
})
.catch(() => setError("Failed to fetch stars"));
}
getCachedGithubStars()
.then((starCount) => {
setStars(starCount);
})
.catch(() => setError("Failed to fetch stars"));
}, []);

return (
Expand Down
77 changes: 4 additions & 73 deletions eduaid_web/src/pages/Output.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import logoPNG from "../assets/aossie_logo_transparent.png";
import { Link } from "react-router-dom";
import apiClient from "../utils/apiClient";
import { FiShuffle, FiEdit2, FiCheck, FiX } from "react-icons/fi";
import { parseQaPairs, shuffleArray } from "../utils/quizUtils";

const Output = () => {
const [qaPairs, setQaPairs] = useState([]);
Expand All @@ -29,15 +30,6 @@ const Output = () => {
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);

function shuffleArray(array) {
const shuffledArray = [...array];
for (let i = shuffledArray.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
}
return shuffledArray;
}

const shuffledOptionsMap = useMemo(() => {
return qaPairs.map((qaPair) => {
const combinedOptions = qaPair.options
Expand Down Expand Up @@ -91,70 +83,9 @@ const Output = () => {
};

useEffect(() => {
const qaPairsFromStorage =
JSON.parse(localStorage.getItem("qaPairs")) || {};
if (qaPairsFromStorage) {
const combinedQaPairs = [];

if (qaPairsFromStorage["output_boolq"]) {
qaPairsFromStorage["output_boolq"]["Boolean_Questions"].forEach(
(question, index) => {
combinedQaPairs.push({
question,
question_type: "Boolean",
context: qaPairsFromStorage["output_boolq"]["Text"],
});
}
);
}

if (qaPairsFromStorage["output_mcq"]) {
qaPairsFromStorage["output_mcq"]["questions"].forEach((qaPair) => {
combinedQaPairs.push({
question: qaPair.question_statement,
question_type: "MCQ",
options: qaPair.options,
answer: qaPair.answer,
context: qaPair.context,
});
});
}

if (qaPairsFromStorage["output_mcq"] || questionType === "get_mcq") {
qaPairsFromStorage["output"].forEach((qaPair) => {
combinedQaPairs.push({
question: qaPair.question_statement,
question_type: "MCQ",
options: qaPair.options,
answer: qaPair.answer,
context: qaPair.context,
});
});
}

if (questionType == "get_boolq") {
qaPairsFromStorage["output"].forEach((qaPair) => {
combinedQaPairs.push({
question: qaPair,
question_type: "Boolean",
});
});
} else if (qaPairsFromStorage["output"] && questionType !== "get_mcq") {
qaPairsFromStorage["output"].forEach((qaPair) => {
combinedQaPairs.push({
question:
qaPair.question || qaPair.question_statement || qaPair.Question,
options: qaPair.options,
answer: qaPair.answer || qaPair.Answer,
context: qaPair.context,
question_type: "Short",
});
});
}

setQaPairs(combinedQaPairs);
}
}, []);
const qaPairsFromStorage = JSON.parse(localStorage.getItem("qaPairs") || "{}");
setQaPairs(parseQaPairs(qaPairsFromStorage, questionType));
}, [questionType]);

const generateGoogleForm = async () => {
try {
Expand Down
30 changes: 15 additions & 15 deletions eduaid_web/src/pages/Question_Type.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,14 @@ const Question_Type = () => {
</span>
</div>
</Link>

<button
type="button"
{/* Title */}
<div className="text-center">
<h2 className="text-white text-3xl sm:text-4xl font-extrabold">
What’s on your Mind?
</h2>
<p className="text-white text-lg sm:text-xl font-medium mt-2">
Choose one
</p>
</div>

aria-pressed={selectedOption === option.id}
{/* Options */}
<div className="flex flex-col items-center mt-8 gap-4 w-full">
{[
Expand Down Expand Up @@ -76,30 +73,33 @@ const Question_Type = () => {
<div className="text-white text-xl sm:text-2xl font-medium">
{option.label}
</div>
</div>
</button>
))}
</div>

{/* Action Button */}
<div className="text-center mt-10">
{selectedOption ? (
<Link to="/input">
<button
onClick={handleSaveToLocalStorage}
className="rounded-2xl text-xl sm:text-2xl text-white px-6 sm:px-8 font-bold py-3 bg-gradient-to-r from-[#FF005C] via-[#7600F2] to-[#00CBE7] hover:brightness-110 transition-all"
>
Fire Up 🚀
</button>
<Link
to="/input"
onClick={handleSaveToLocalStorage}
className="inline-block rounded-2xl text-xl sm:text-2xl text-white px-6 sm:px-8 font-bold py-3 bg-gradient-to-r from-[#FF005C] via-[#7600F2] to-[#00CBE7] hover:brightness-110 transition-all"
>
Fire Up 🚀
</Link>
) : (
<button
onClick={() => alert("Please select a question type.")}
type="button"
className="rounded-2xl text-xl sm:text-2xl text-white px-6 sm:px-8 font-bold py-3 bg-gray-500 cursor-not-allowed"
disabled
aria-disabled="true"
>
Fire Up 🚀
</button>
)}
{!selectedOption && (
<p className="text-white text-sm mt-3">Select a question type to continue.</p>
)}
</div>
</div>
</div>
Expand Down
47 changes: 14 additions & 33 deletions eduaid_web/src/pages/Text_Input.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { FaClipboard } from "react-icons/fa";
import Switch from "react-switch";
import { Link,useNavigate } from "react-router-dom";
import apiClient from "../utils/apiClient";
import { getEndpointForQuestionType, saveQuizHistory } from "../utils/quizUtils";

const Text_Input = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -73,6 +74,8 @@ const Text_Input = () => {
difficulty,
localStorage.getItem("selectedQuestionType")
);
} else {
setLoading(false);
}
};

Expand All @@ -88,19 +91,8 @@ const Text_Input = () => {
setNumQuestions((prev) => (prev > 0 ? prev - 1 : 0));
};

const getEndpoint = (difficulty, questionType) => {
if (difficulty !== "Easy Difficulty") {
if (questionType === "get_shortq") {
return "get_shortq_hard";
} else if (questionType === "get_mcq") {
return "get_mcq_hard";
}
}
return questionType;
};

const sendToBackend = async (data, difficulty, questionType) => {
const endpoint = getEndpoint(difficulty, questionType);
const endpoint = getEndpointForQuestionType(difficulty, questionType);
try {
const requestData = {
input_text: data,
Expand All @@ -110,22 +102,7 @@ const Text_Input = () => {

const responseData = await apiClient.post(`/${endpoint}`, requestData);
localStorage.setItem("qaPairs", JSON.stringify(responseData));

// Save quiz details to local storage
const quizDetails = {
difficulty,
numQuestions,
date: new Date().toLocaleDateString(),
qaPair: responseData,
};

let last5Quizzes =
JSON.parse(localStorage.getItem("last5Quizzes")) || [];
last5Quizzes.push(quizDetails);
if (last5Quizzes.length > 5) {
last5Quizzes.shift(); // Keep only the last 5 quizzes
}
localStorage.setItem("last5Quizzes", JSON.stringify(last5Quizzes));
saveQuizHistory({ difficulty, numQuestions, qaPair: responseData });

navigate("/output");
} catch (error) {
Expand Down Expand Up @@ -167,10 +144,11 @@ const Text_Input = () => {

{/* Textarea */}
<div className="relative bg-[#83b6cc40] mx-4 sm:mx-8 rounded-2xl p-4 min-h-[160px] sm:min-h-[200px] mt-4">
<button className="absolute top-0 left-0 p-2 text-white focus:outline-none">
<span className="absolute top-0 left-0 p-2 text-white" aria-hidden="true">
<FaClipboard className="h-[24px] w-[24px]" />
</button>
</span>
<textarea
aria-label="Content input"
className="absolute inset-0 p-8 pt-6 bg-[#83b6cc40] text-lg sm:text-xl rounded-2xl outline-none resize-none h-full overflow-y-auto text-white caret-white"
style={{ scrollbarWidth: "none", msOverflowStyle: "none" }}
value={text}
Expand All @@ -187,8 +165,10 @@ const Text_Input = () => {
<img className="mx-auto mb-2" height={32} width={32} src={cloud} alt="cloud" />
<p className="text-white text-lg">Choose a file (PDF, MP3 supported)</p>

<input type="file" ref={fileInputRef} onChange={handleFileUpload} style={{ display: "none" }} />
<input type="file" accept=".pdf,.mp3,.wav,.txt" ref={fileInputRef} onChange={handleFileUpload} style={{ display: "none" }} />
Comment thread
ashi2004 marked this conversation as resolved.
<button
type="button"
aria-label="Browse and upload a file"
className="bg-[#3e506380] my-4 text-lg rounded-2xl text-white border border-[#cbd0dc80] px-6 py-2"
onClick={handleClick}
>
Expand All @@ -209,9 +189,9 @@ const Text_Input = () => {
{/* Question Count */}
<div className="flex gap-2 items-center">
<div className="text-white text-lg sm:text-xl font-bold">No. of Questions:</div>
<button onClick={decrementQuestions} className="rounded-lg border-2 border-[#6e8a9f] text-white text-xl px-3">-</button>
<button type="button" aria-label="Decrease number of questions" onClick={decrementQuestions} className="rounded-lg border-2 border-[#6e8a9f] text-white text-xl px-3">-</button>
<span className="text-white text-2xl">{numQuestions}</span>
<button onClick={incrementQuestions} className="rounded-lg border-2 border-[#6e8a9f] text-white text-xl px-3">+</button>
<button type="button" aria-label="Increase number of questions" onClick={incrementQuestions} className="rounded-lg border-2 border-[#6e8a9f] text-white text-xl px-3">+</button>
</div>

{/* Difficulty Dropdown */}
Expand Down Expand Up @@ -246,6 +226,7 @@ const Text_Input = () => {
<button className="bg-black text-white text-lg sm:text-xl px-4 py-2 border-gradient rounded-xl w-full sm:w-auto">Back</button>
</Link>
<button
type="button"
onClick={handleSaveToLocalStorage}
className="bg-black text-white text-lg sm:text-xl px-4 py-2 border-gradient flex justify-center items-center rounded-xl w-full sm:w-auto"
>
Expand Down
31 changes: 31 additions & 0 deletions eduaid_web/src/utils/githubStars.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const STARS_KEY = "stars";
const FETCH_TIME_KEY = "fetchTime";
Comment thread
ashi2004 marked this conversation as resolved.
const ONE_DAY_MS = 24 * 60 * 60 * 1000;

function isMoreThanOneDayOld(timestamp) {
return Date.now() - timestamp > ONE_DAY_MS;
}

async function fetchGithubStars() {
const response = await fetch("https://api.github.com/repos/AOSSIE-Org/EduAid");
if (!response.ok) {
throw new Error("Failed to fetch stars");
}

const data = await response.json();
return data.stargazers_count;
}

export async function getCachedGithubStars() {
const storedStars = localStorage.getItem(STARS_KEY);
const storedTime = localStorage.getItem(FETCH_TIME_KEY);

if (storedStars && storedTime && !isMoreThanOneDayOld(Number(storedTime))) {
return Number(storedStars);
}

const stars = await fetchGithubStars();
localStorage.setItem(STARS_KEY, String(stars));
localStorage.setItem(FETCH_TIME_KEY, String(Date.now()));
return stars;
}
Loading