Separate Submit Quiz button from Generate Google Form button#557
Separate Submit Quiz button from Generate Google Form button#557PunyaGowdagd66 wants to merge 3 commits intoAOSSIE-Org:mainfrom
Conversation
📝 WalkthroughWalkthroughTwo UI components were enhanced: the Output page now enables interactive answer selection with quiz scoring functionality, while the Text_Input page adds validation to prevent saving when neither file upload nor text input is provided. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
eduaid_web/src/pages/Output.jsx (3)
217-222:⚠️ Potential issue | 🟠 MajorHide the correct answer while the quiz is active.
The new submit flow is not meaningful while Lines 217-222 still render
qaPair.answerbefore the user chooses anything. Gate that block behind a post-submit/show-answers state or this becomes an open-book score screen.Also applies to: 258-263
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@eduaid_web/src/pages/Output.jsx` around lines 217 - 222, The Answer display currently renders qaPair.answer unconditionally (blocks that include "Answer" label and {qaPair.answer} around qaPair) which leaks correct responses during an active quiz; wrap both occurrences (the block rendering {qaPair.answer} at lines shown and the similar block at 258-263) behind a boolean like quizSubmitted or showAnswers (prop/state) and only render the answer block when that flag is true; update the component (Output.jsx) to check this flag before rendering the "Answer" label and {qaPair.answer}, and ensure the flag is toggled when the user submits or when show-answers mode is activated.
199-203:⚠️ Potential issue | 🟠 MajorKeep option order stable after a selection.
Each click updates
userAnswersstate, triggering a rerender of the question list. SinceshuffleArray()usesMath.random()and runs during render at line 203, the options reorder unpredictably after every selection. Shuffle once when loadingqaPairsor memoize the shuffled options per question to maintain consistent UI.Also applies to: 226-230
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@eduaid_web/src/pages/Output.jsx` around lines 199 - 203, The options are being re-shuffled on every render because shuffleArray(...) is called inside qaPairs.map during render (in the component that maps qaPairs and sets userAnswers), causing option order to change after each selection; fix by computing a stable shuffled options list once per question—either shuffle when qaPairs are first loaded (in the data-loading logic) or create a memoized mapping of questionId/index → shuffledOptions using useMemo or useState (e.g., build shuffledOptionsForQuestion keyed by qaPair.id or index) and reference that inside the qaPairs.map instead of calling shuffleArray each render; update code locations around qaPairs.map and the shuffleArray usage at lines ~203 and ~226-230 to use the stable memoized/stored shuffled options.
226-237:⚠️ Potential issue | 🟠 MajorReplace clickable div with semantic button control and display selected state.
The current
divelement is not keyboard accessible (no keyboard event handlers, not a semantic interactive element), and the selected answer choice is never visually reflected in the UI despite theuserAnswersstate tracking selections. Users cannot reliably tell what they've selected. This should be abuttonelement witharia-pressedstate and selected styling applied based onuserAnswers.Suggested fix
- <div - key={idx} - className="mb-1 sm:mb-2 cursor-pointer" - onClick={() => handleAnswerSelect(index, option)} - > + <button + type="button" + key={idx} + className={`mb-1 sm:mb-2 w-full rounded-lg px-2 py-1 text-left cursor-pointer ${ + userAnswers[index] === option + ? "bg-[`#518E8E`]/30 ring-1 ring-[`#518E8E`]" + : "" + }`} + aria-pressed={userAnswers[index] === option} + onClick={() => handleAnswerSelect(index, option)} + > <span className="text-[`#E4E4E4`] text-xs sm:text-sm"> Option {idx + 1}: </span>{" "} <span className="text-[`#FFF4F4`] text-sm sm:text-base"> {option} </span> - </div> + </button>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@eduaid_web/src/pages/Output.jsx` around lines 226 - 237, Replace the non-interactive div used for answer choices with a semantic button in the mapping that calls handleAnswerSelect(index, option); use the component state userAnswers (e.g. check userAnswers[index] === option) to set aria-pressed and to conditionally apply "selected" styling classes so the choice is visibly different when chosen; keep the existing key={idx}, preserve the displayed text ("Option {idx + 1}:" and {option}), and ensure the onClick still invokes handleAnswerSelect (no extra keyboard handlers needed for a native button).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@eduaid_web/src/pages/Text_Input.jsx`:
- Around line 51-56: The empty-input guard in Text_Input.jsx uses raw text and
docUrl so whitespace-only input passes; before the check that alerts and
returns, normalize both values (e.g., create trimmedText = text?.trim() and
trimmedDocUrl = docUrl?.trim()) and branch on those trimmed values instead, and
ensure subsequent calls (like the /get_content or quiz generation path) use the
trimmed variables rather than the original text/docUrl so whitespace-only inputs
are rejected.
---
Outside diff comments:
In `@eduaid_web/src/pages/Output.jsx`:
- Around line 217-222: The Answer display currently renders qaPair.answer
unconditionally (blocks that include "Answer" label and {qaPair.answer} around
qaPair) which leaks correct responses during an active quiz; wrap both
occurrences (the block rendering {qaPair.answer} at lines shown and the similar
block at 258-263) behind a boolean like quizSubmitted or showAnswers
(prop/state) and only render the answer block when that flag is true; update the
component (Output.jsx) to check this flag before rendering the "Answer" label
and {qaPair.answer}, and ensure the flag is toggled when the user submits or
when show-answers mode is activated.
- Around line 199-203: The options are being re-shuffled on every render because
shuffleArray(...) is called inside qaPairs.map during render (in the component
that maps qaPairs and sets userAnswers), causing option order to change after
each selection; fix by computing a stable shuffled options list once per
question—either shuffle when qaPairs are first loaded (in the data-loading
logic) or create a memoized mapping of questionId/index → shuffledOptions using
useMemo or useState (e.g., build shuffledOptionsForQuestion keyed by qaPair.id
or index) and reference that inside the qaPairs.map instead of calling
shuffleArray each render; update code locations around qaPairs.map and the
shuffleArray usage at lines ~203 and ~226-230 to use the stable memoized/stored
shuffled options.
- Around line 226-237: Replace the non-interactive div used for answer choices
with a semantic button in the mapping that calls handleAnswerSelect(index,
option); use the component state userAnswers (e.g. check userAnswers[index] ===
option) to set aria-pressed and to conditionally apply "selected" styling
classes so the choice is visibly different when chosen; keep the existing
key={idx}, preserve the displayed text ("Option {idx + 1}:" and {option}), and
ensure the onClick still invokes handleAnswerSelect (no extra keyboard handlers
needed for a native button).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c981aeb3-04bb-4925-a1f4-7250a12c32b0
⛔ Files ignored due to path filters (1)
eduaid_web/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (2)
eduaid_web/src/pages/Output.jsxeduaid_web/src/pages/Text_Input.jsx
| if (!text && !docUrl) { | ||
| alert("Please upload a file or provide input before proceeding."); | ||
| return; | ||
| } | ||
|
|
||
| setLoading(true); |
There was a problem hiding this comment.
Trim the inputs before applying this empty-input guard.
" " currently passes the check and can still hit /get_content or quiz generation with blank content. Normalize both fields once and branch on the trimmed values instead.
Suggested fix
const handleSaveToLocalStorage = async () => {
-
- if (!text && !docUrl) {
- alert("Please upload a file or provide input before proceeding.");
- return;
- }
+ const trimmedText = text.trim();
+ const trimmedDocUrl = docUrl.trim();
+
+ if (!trimmedText && !trimmedDocUrl) {
+ alert("Please upload a file or provide input before proceeding.");
+ return;
+ }
- setLoading(true);
+ setLoading(true);
// Check if a Google Doc URL is provided
- if (docUrl) {
+ if (trimmedDocUrl) {
try {
- const data = await apiClient.post("/get_content", { document_url: docUrl });
+ const data = await apiClient.post("/get_content", { document_url: trimmedDocUrl });
setDocUrl("");
setText(data || "Error in retrieving");
} catch (error) {
console.error("Error:", error);
setText("Error retrieving Google Doc content");
} finally {
setLoading(false);
}
- } else if (text) {
+ } else if (trimmedText) {
// Proceed with existing functionality for local storage
- localStorage.setItem("textContent", text);
+ localStorage.setItem("textContent", trimmedText);
localStorage.setItem("difficulty", difficulty);
localStorage.setItem("numQuestions", numQuestions);
await sendToBackend(
- text,
+ trimmedText,
difficulty,
localStorage.getItem("selectedQuestionType")
);
}
};🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@eduaid_web/src/pages/Text_Input.jsx` around lines 51 - 56, The empty-input
guard in Text_Input.jsx uses raw text and docUrl so whitespace-only input
passes; before the check that alerts and returns, normalize both values (e.g.,
create trimmedText = text?.trim() and trimmedDocUrl = docUrl?.trim()) and branch
on those trimmed values instead, and ensure subsequent calls (like the
/get_content or quiz generation path) use the trimmed variables rather than the
original text/docUrl so whitespace-only inputs are rejected.
Changes
setUserAnswersto functional state update to avoid stale state problems.This PR resolves critical UI bugs and ensures a smoother quiz-taking experience.
Summary by CodeRabbit
New Features
Bug Fixes