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
202 changes: 99 additions & 103 deletions frontend/src/components/dsa/questions/QuestionView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,69 +48,67 @@ export function QuestionsView({ selectedTopic, onBack }) {
};

const difficulties = ["All", "Easy", "Medium", "Hard"];


return (
<section className="min-h-screen py-10">
<section className="min-h-screen py-6 sm:py-8 lg:py-10">
{/* ---------- HEADER ---------- */}
<div className="flex flex-col md:flex-row justify-between items-center mb-12 gap-6">
<div className="flex flex-col gap-4 sm:gap-5 lg:gap-6 mb-8 sm:mb-10 lg:mb-12">
{/* Back Button */}
<div className="relative">
<div className="relative w-full sm:w-auto">
<div
aria-hidden="true"
className="absolute inset-0 translate-x-2 translate-y-2 bg-[#2C1810] dark:bg-[#F5E6D3]"
className="absolute inset-0 translate-x-1.5 translate-y-1.5 sm:translate-x-2 sm:translate-y-2 bg-[#2C1810] dark:bg-[#F5E6D3]"
/>
<button
onClick={onBack}
className="relative border-4 border-black bg-[#2C1810] dark:bg-[#F5E6D3] text-[#F5E6D3] dark:text-[#2C1810] px-6 py-3 font-extrabold flex items-center gap-2 shadow-[6px_6px_0_0_rgba(0,0,0,1)] hover:-translate-x-1 hover:-translate-y-1 transition-transform"
className="relative w-full sm:w-auto border-3 sm:border-4 border-black bg-[#2C1810] dark:bg-[#F5E6D3] text-[#F5E6D3] dark:text-[#2C1810] px-5 py-2.5 sm:px-6 sm:py-3 font-extrabold flex items-center justify-center gap-2 shadow-[4px_4px_0_0_rgba(0,0,0,1)] sm:shadow-[6px_6px_0_0_rgba(0,0,0,1)] hover:-translate-x-1 hover:-translate-y-1 transition-transform text-sm sm:text-base"
>
<ArrowLeft className="w-5 h-5" />
<ArrowLeft className="w-4 h-4 sm:w-5 sm:h-5" />
BACK TO TOPICS
</button>
</div>

{/* Topic Tag */}
<div className="relative">
<div className="relative w-full sm:w-auto sm:self-start">
<div
aria-hidden="true"
className="absolute inset-0 translate-x-2 translate-y-2 bg-[#2C1810] dark:bg-[#F5E6D3]"
className="absolute inset-0 translate-x-1.5 translate-y-1.5 sm:translate-x-2 sm:translate-y-2 bg-[#2C1810] dark:bg-[#F5E6D3]"
/>
<button className="relative border-4 border-black bg-[#C1502E] text-white px-6 py-3 font-extrabold shadow-[6px_6px_0_0_rgba(0,0,0,1)]">
<button className="relative w-full sm:w-auto border-3 sm:border-4 border-black bg-[#C1502E] text-white px-5 py-2.5 sm:px-6 sm:py-3 font-extrabold shadow-[4px_4px_0_0_rgba(0,0,0,1)] sm:shadow-[6px_6px_0_0_rgba(0,0,0,1)] text-sm sm:text-base">
{selectedTopic.title}
</button>
</div>
Comment on lines +73 to 81
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Non-interactive element rendered as <button>.

The topic tag (Line 78) is a <button> with no onClick handler — it's purely presentational. This misleads assistive technology into announcing it as an interactive control. Use a <span> or <div> instead, and keep the same styling classes.

Proposed fix
-          <button className="relative w-full sm:w-auto border-3 sm:border-4 border-black bg-[`#C1502E`] text-white px-5 py-2.5 sm:px-6 sm:py-3 font-extrabold shadow-[4px_4px_0_0_rgba(0,0,0,1)] sm:shadow-[6px_6px_0_0_rgba(0,0,0,1)] text-sm sm:text-base">
+          <span className="relative inline-block w-full sm:w-auto border-3 sm:border-4 border-black bg-[`#C1502E`] text-white px-5 py-2.5 sm:px-6 sm:py-3 font-extrabold shadow-[4px_4px_0_0_rgba(0,0,0,1)] sm:shadow-[6px_6px_0_0_rgba(0,0,0,1)] text-sm sm:text-base">
            {selectedTopic.title}
-          </button>
+          </span>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="relative w-full sm:w-auto sm:self-start">
<div
aria-hidden="true"
className="absolute inset-0 translate-x-2 translate-y-2 bg-[#2C1810] dark:bg-[#F5E6D3]"
className="absolute inset-0 translate-x-1.5 translate-y-1.5 sm:translate-x-2 sm:translate-y-2 bg-[#2C1810] dark:bg-[#F5E6D3]"
/>
<button className="relative border-4 border-black bg-[#C1502E] text-white px-6 py-3 font-extrabold shadow-[6px_6px_0_0_rgba(0,0,0,1)]">
<button className="relative w-full sm:w-auto border-3 sm:border-4 border-black bg-[#C1502E] text-white px-5 py-2.5 sm:px-6 sm:py-3 font-extrabold shadow-[4px_4px_0_0_rgba(0,0,0,1)] sm:shadow-[6px_6px_0_0_rgba(0,0,0,1)] text-sm sm:text-base">
{selectedTopic.title}
</button>
</div>
<div className="relative w-full sm:w-auto sm:self-start">
<div
aria-hidden="true"
className="absolute inset-0 translate-x-1.5 translate-y-1.5 sm:translate-x-2 sm:translate-y-2 bg-[`#2C1810`] dark:bg-[`#F5E6D3`]"
/>
<span className="relative inline-block w-full sm:w-auto border-3 sm:border-4 border-black bg-[`#C1502E`] text-white px-5 py-2.5 sm:px-6 sm:py-3 font-extrabold shadow-[4px_4px_0_0_rgba(0,0,0,1)] sm:shadow-[6px_6px_0_0_rgba(0,0,0,1)] text-sm sm:text-base">
{selectedTopic.title}
</span>
</div>
🤖 Prompt for AI Agents
In `@frontend/src/components/dsa/questions/QuestionView.jsx` around lines 73 - 81,
The topic tag is rendered as a non-interactive <button> (the element containing
selectedTopic.title in QuestionView.jsx) but has no onClick; change that
<button> to a presentational element like <span> or <div> (keeping the same
className and styling such as border-3, bg-[`#C1502E`], font-extrabold, shadow
etc.), remove any button-specific attributes, and if the element actually needs
to be interactive instead add a proper onClick handler and keyboard handling;
ensure the replacement still renders selectedTopic.title.

</div>

{/* ---------- SEARCH + FILTER ---------- */}
<div className="mb-12">
<div className="mb-8 sm:mb-10 lg:mb-12">
<SearchBar
searchTerm={searchTerm}
onSearchChange={setSearchTerm}
placeholder="Search questions..."
/>

<div className="mt-10">
<p className="text-lg font-extrabold text-[#2C1810] dark:text-[#F5E6D3] mb-4 tracking-wide">
<div className="mt-6 sm:mt-8 lg:mt-10">
<p className="text-base sm:text-lg font-extrabold text-[#2C1810] dark:text-[#F5E6D3] mb-3 sm:mb-4 tracking-wide">
FILTER BY DIFFICULTY
</p>
<div className="flex flex-wrap gap-4">
<div className="flex flex-wrap gap-3 sm:gap-4">
{difficulties.map((diff) => (
<div key={diff} className="relative">
<div
aria-hidden="true"
className={`absolute inset-0 translate-x-2 translate-y-2 ${
difficultyFilter === diff
className={`absolute inset-0 translate-x-1.5 translate-y-1.5 sm:translate-x-2 sm:translate-y-2 ${difficultyFilter === diff
? "bg-[#2C1810] dark:bg-[#F5E6D3]"
: "bg-transparent"
}`}
}`}
/>
<button
onClick={() => setDifficultyFilter(diff)}
className={`relative border-4 border-black px-6 py-2 font-extrabold shadow-[5px_5px_0_0_rgba(0,0,0,1)] transition-all duration-200 ${
difficultyFilter === diff
className={`relative border-3 sm:border-4 border-black px-4 py-1.5 sm:px-6 sm:py-2 font-extrabold shadow-[3px_3px_0_0_rgba(0,0,0,1)] sm:shadow-[5px_5px_0_0_rgba(0,0,0,1)] transition-all duration-200 text-sm sm:text-base ${difficultyFilter === diff
? "bg-[#C1502E] text-white"
: "bg-[#FFF6EE] text-[#2C1810] hover:-translate-x-1 hover:-translate-y-1"
}`}
}`}
>
{diff.toUpperCase()}
</button>
Expand All @@ -123,94 +121,92 @@ export function QuestionsView({ selectedTopic, onBack }) {
{/* ---------- QUESTIONS ---------- */}
{isLoading ? (
<div className="flex justify-center items-center h-64">
<Loader2 className="w-10 h-10 animate-spin text-[#C1502E]" />
<Loader2 className="w-8 h-8 sm:w-10 sm:h-10 animate-spin text-[#C1502E]" />
</div>
) : filteredQuestions.length === 0 ? (
<EmptyState icon={FileText} message="No questions found" />
) : (
<div className="space-y-8">
<div className="space-y-5 sm:space-y-6 lg:space-y-8">
{filteredQuestions.map((question) => (
<div key={question.id} className="relative group mb-12">
{/* Layered block background (non-interactive) */}
<div
className="absolute inset-0 -rotate-1 translate-x-3 translate-y-3 bg-[#2C1810] dark:bg-[#F5E6D3] rounded-lg transition-all duration-500 group-hover:translate-x-4 group-hover:translate-y-4 pointer-events-none"
/>
<div
className="absolute inset-0 rotate-2 translate-x-1 translate-y-1 bg-[#b05a3c]/60 rounded-lg blur-[1px] pointer-events-none"
/>

{/* Main floating card */}
<div
className="relative border-4 border-black bg-[#FFF6EE] dark:bg-[#2C1810]
p-8 rounded-lg shadow-[10px_10px_0_0_#2C1810]
hover:shadow-[12px_12px_0_0_#C1502E]
transition-all duration-300 hover:-translate-y-2"
>
{/* Header */}
<div className="flex items-start justify-between gap-6">
<div className="flex-1">
<h3
className={`text-2xl font-extrabold leading-snug ${
completedMap[question.id]
? "text-[#a88d80] line-through"
: "text-[#2C1810] dark:text-[#F5E6D3]"
}`}
>
{question.questionName}
</h3>
</div>

<div
className={`text-sm font-black tracking-wider border-4 border-black
px-4 py-1 bg-[#C1502E] text-[#FFF6EE] dark:bg-[#F5E6D3] dark:text-[#2C1810]
shadow-[3px_3px_0_0_#2C1810]`}
>
{question.difficulty.toUpperCase()}
</div>
</div>

{/* Divider bar */}
<div className="h-1 mt-5 mb-6 bg-[#C1502E] dark:bg-[#F5E6D3] rounded-full w-2/3 group-hover:w-full transition-all duration-300"></div>

{/* Actions */}
<div className="flex justify-between items-center">
<button
onClick={() => handleToggle(question.id)}
disabled={toggle.isPending}
className={`flex items-center gap-3 font-extrabold text-[#2C1810] dark:text-[#F5E6D3] ${
toggle.isPending ? "opacity-60 cursor-not-allowed" : ""
}`}
>
{completedMap[question.id] ? (
<CheckCircle2 className="w-8 h-8 text-[#3dd68c]" />
) : (
<Circle className="w-8 h-8 text-[#b05a3c] dark:text-[#F5E6D3]" />
)}
<span className="text-sm uppercase">
{toggle.isPending ? "Updating..." : "Mark Done"}
</span>
</button>

<button
onClick={() =>
window.open(question.link, "_blank", "noopener,noreferrer")
}
className="relative border-4 border-black bg-[#F5E6D3] dark:bg-[#FFF6EE]
p-3 font-black hover:-translate-x-0.5 hover:-translate-y-0.5
shadow-[4px_4px_0_0_#2C1810] transition-transform group/link"
>
<ExternalLink className="w-5 h-5 text-[#2C1810]" />
<span className="absolute -bottom-5 left-0 opacity-0 group-hover/link:opacity-100 text-xs font-extrabold text-[#2C1810] dark:text-[#F5E6D3] transition-all">
Open
</span>
</button>
</div>

{/* Floating animated accent */}
<div className="absolute -bottom-2 right-6 w-20 h-20 bg-gradient-to-tr from-[#C1502E40] to-transparent blur-2xl rounded-full animate-pulse pointer-events-none" />
</div>
</div>
))}
<div key={question.id} className="relative group mb-6 sm:mb-8 lg:mb-12">
Comment on lines +129 to +131
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Double vertical spacing — space-y-* on parent compounds with mb-* on children.

Line 129 applies space-y-5 sm:space-y-6 lg:space-y-8 to the container, which adds margin-top to every sibling. Line 131 also adds mb-6 sm:mb-8 lg:mb-12 to each card. This stacks both margins between cards, producing larger gaps than intended.

Pick one approach — either space-y-* on the parent or mb-* on the children — not both.

Proposed fix — remove mb from children
-            <div key={question.id} className="relative group mb-6 sm:mb-8 lg:mb-12">
+            <div key={question.id} className="relative group">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="space-y-5 sm:space-y-6 lg:space-y-8">
{filteredQuestions.map((question) => (
<div key={question.id} className="relative group mb-12">
{/* Layered block background (non-interactive) */}
<div
className="absolute inset-0 -rotate-1 translate-x-3 translate-y-3 bg-[#2C1810] dark:bg-[#F5E6D3] rounded-lg transition-all duration-500 group-hover:translate-x-4 group-hover:translate-y-4 pointer-events-none"
/>
<div
className="absolute inset-0 rotate-2 translate-x-1 translate-y-1 bg-[#b05a3c]/60 rounded-lg blur-[1px] pointer-events-none"
/>
{/* Main floating card */}
<div
className="relative border-4 border-black bg-[#FFF6EE] dark:bg-[#2C1810]
p-8 rounded-lg shadow-[10px_10px_0_0_#2C1810]
hover:shadow-[12px_12px_0_0_#C1502E]
transition-all duration-300 hover:-translate-y-2"
>
{/* Header */}
<div className="flex items-start justify-between gap-6">
<div className="flex-1">
<h3
className={`text-2xl font-extrabold leading-snug ${
completedMap[question.id]
? "text-[#a88d80] line-through"
: "text-[#2C1810] dark:text-[#F5E6D3]"
}`}
>
{question.questionName}
</h3>
</div>
<div
className={`text-sm font-black tracking-wider border-4 border-black
px-4 py-1 bg-[#C1502E] text-[#FFF6EE] dark:bg-[#F5E6D3] dark:text-[#2C1810]
shadow-[3px_3px_0_0_#2C1810]`}
>
{question.difficulty.toUpperCase()}
</div>
</div>
{/* Divider bar */}
<div className="h-1 mt-5 mb-6 bg-[#C1502E] dark:bg-[#F5E6D3] rounded-full w-2/3 group-hover:w-full transition-all duration-300"></div>
{/* Actions */}
<div className="flex justify-between items-center">
<button
onClick={() => handleToggle(question.id)}
disabled={toggle.isPending}
className={`flex items-center gap-3 font-extrabold text-[#2C1810] dark:text-[#F5E6D3] ${
toggle.isPending ? "opacity-60 cursor-not-allowed" : ""
}`}
>
{completedMap[question.id] ? (
<CheckCircle2 className="w-8 h-8 text-[#3dd68c]" />
) : (
<Circle className="w-8 h-8 text-[#b05a3c] dark:text-[#F5E6D3]" />
)}
<span className="text-sm uppercase">
{toggle.isPending ? "Updating..." : "Mark Done"}
</span>
</button>
<button
onClick={() =>
window.open(question.link, "_blank", "noopener,noreferrer")
}
className="relative border-4 border-black bg-[#F5E6D3] dark:bg-[#FFF6EE]
p-3 font-black hover:-translate-x-0.5 hover:-translate-y-0.5
shadow-[4px_4px_0_0_#2C1810] transition-transform group/link"
>
<ExternalLink className="w-5 h-5 text-[#2C1810]" />
<span className="absolute -bottom-5 left-0 opacity-0 group-hover/link:opacity-100 text-xs font-extrabold text-[#2C1810] dark:text-[#F5E6D3] transition-all">
Open
</span>
</button>
</div>
{/* Floating animated accent */}
<div className="absolute -bottom-2 right-6 w-20 h-20 bg-gradient-to-tr from-[#C1502E40] to-transparent blur-2xl rounded-full animate-pulse pointer-events-none" />
</div>
</div>
))}
<div key={question.id} className="relative group mb-6 sm:mb-8 lg:mb-12">
<div className="space-y-5 sm:space-y-6 lg:space-y-8">
{filteredQuestions.map((question) => (
<div key={question.id} className="relative group">
🤖 Prompt for AI Agents
In `@frontend/src/components/dsa/questions/QuestionView.jsx` around lines 129 -
131, The parent container using className "space-y-5 sm:space-y-6 lg:space-y-8"
and each child div (inside filteredQuestions.map) using "mb-6 sm:mb-8 lg:mb-12"
cause doubled vertical gaps; choose one method—remove the per-card margins on
the child div (the div rendered in filteredQuestions.map with key={question.id})
so spacing is controlled solely by the parent's space-y-* classes, i.e., delete
the mb-* utilities from that child element's className.

{/* Layered block background (non-interactive) */}
<div
className="hidden sm:block absolute inset-0 -rotate-1 translate-x-2 translate-y-2 sm:translate-x-3 sm:translate-y-3 bg-[#2C1810] dark:bg-[#F5E6D3] rounded-lg transition-all duration-500 group-hover:translate-x-3 group-hover:translate-y-3 sm:group-hover:translate-x-4 sm:group-hover:translate-y-4 pointer-events-none"
/>
<div
className="hidden sm:block absolute inset-0 rotate-2 translate-x-0.5 translate-y-0.5 sm:translate-x-1 sm:translate-y-1 bg-[#b05a3c]/60 rounded-lg blur-[1px] pointer-events-none"
/>

{/* Main floating card */}
<div
className="relative border-3 sm:border-4 border-black bg-[#FFF6EE] dark:bg-[#2C1810]
p-5 sm:p-6 lg:p-8 rounded-lg shadow-[4px_4px_0_0_#2C1810] sm:shadow-[8px_8px_0_0_#2C1810] lg:shadow-[10px_10px_0_0_#2C1810]
hover:shadow-[6px_6px_0_0_#C1502E] sm:hover:shadow-[10px_10px_0_0_#C1502E] lg:hover:shadow-[12px_12px_0_0_#C1502E]
transition-all duration-300 hover:-translate-y-1 sm:hover:-translate-y-2"
>
{/* Header */}
<div className="flex flex-col sm:flex-row items-start justify-between gap-3 sm:gap-4 lg:gap-6">
<div className="flex-1">
<h3
className={`text-lg sm:text-xl lg:text-2xl font-extrabold leading-snug ${completedMap[question.id]
? "text-[#a88d80] line-through"
: "text-[#2C1810] dark:text-[#F5E6D3]"
}`}
>
{question.questionName}
</h3>
</div>

<div
className={`text-xs sm:text-sm font-black tracking-wider border-2 sm:border-3 lg:border-4 border-black
px-3 py-1 sm:px-4 sm:py-1 bg-[#C1502E] text-[#FFF6EE] dark:bg-[#F5E6D3] dark:text-[#2C1810]
shadow-[2px_2px_0_0_#2C1810] sm:shadow-[3px_3px_0_0_#2C1810] whitespace-nowrap`}
>
{question.difficulty.toUpperCase()}
</div>
</div>

{/* Divider bar */}
<div className="h-0.5 sm:h-1 mt-3 sm:mt-4 lg:mt-5 mb-4 sm:mb-5 lg:mb-6 bg-[#C1502E] dark:bg-[#F5E6D3] rounded-full w-1/2 sm:w-2/3 group-hover:w-full transition-all duration-300"></div>

{/* Actions */}
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 sm:gap-6">
<button
onClick={() => handleToggle(question.id)}
disabled={toggle.isPending}
className={`flex items-center gap-2 sm:gap-3 font-extrabold text-[#2C1810] dark:text-[#F5E6D3] ${toggle.isPending ? "opacity-60 cursor-not-allowed" : ""
}`}
>
{completedMap[question.id] ? (
<CheckCircle2 className="w-7 h-7 sm:w-8 sm:h-8 text-[#3dd68c]" />
) : (
<Circle className="w-7 h-7 sm:w-8 sm:h-8 text-[#b05a3c] dark:text-[#F5E6D3]" />
)}
<span className="text-xs sm:text-sm uppercase">
{toggle.isPending ? "Updating..." : "Mark Done"}
</span>
</button>

<button
onClick={() =>
window.open(question.link, "_blank", "noopener,noreferrer")
}
className="relative border-3 sm:border-4 border-black bg-[#F5E6D3] dark:bg-[#FFF6EE]
p-2.5 sm:p-3 font-black hover:-translate-x-0.5 hover:-translate-y-0.5
shadow-[3px_3px_0_0_#2C1810] sm:shadow-[4px_4px_0_0_#2C1810] transition-transform group/link"
>
<ExternalLink className="w-4 h-4 sm:w-5 sm:h-5 text-[#2C1810]" />
<span className="absolute -bottom-4 sm:-bottom-5 left-0 opacity-0 group-hover/link:opacity-100 text-[10px] sm:text-xs font-extrabold text-[#2C1810] dark:text-[#F5E6D3] transition-all">
Open
</span>
</button>
Comment on lines +190 to +202
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing accessible label on the "Open" link button.

The button only contains an <ExternalLink> icon and a tooltip <span> that's opacity-0 by default. Screen readers won't convey the button's purpose. Add an aria-label (or visually-hidden text).

Proposed fix
                  <button
                    onClick={() =>
                      window.open(question.link, "_blank", "noopener,noreferrer")
                    }
-                   className="relative border-3 sm:border-4 border-black bg-[`#F5E6D3`] dark:bg-[`#FFF6EE`] 
+                   aria-label="Open question in new tab"
+                   className="relative border-3 sm:border-4 border-black bg-[`#F5E6D3`] dark:bg-[`#FFF6EE`] 
          p-2.5 sm:p-3 font-black hover:-translate-x-0.5 hover:-translate-y-0.5
          shadow-[3px_3px_0_0_#2C1810] sm:shadow-[4px_4px_0_0_#2C1810] transition-transform group/link"
                  >
🤖 Prompt for AI Agents
In `@frontend/src/components/dsa/questions/QuestionView.jsx` around lines 190 -
202, The button in QuestionView.jsx (the clickable element rendering
<ExternalLink /> inside QuestionView) lacks an accessible label; update the
button element to include a descriptive aria-label (e.g., aria-label={`Open
question: ${question.title || 'link'}`}) or add visually-hidden text inside the
button that conveys “Open” for screen readers, ensuring the existing decorative
<ExternalLink /> and the tooltip <span> remain unchanged; target the button
element in the QuestionView component to implement this change.

</div>

{/* Floating animated accent */}
<div className="absolute -bottom-2 right-4 sm:right-6 w-16 h-16 sm:w-20 sm:h-20 bg-gradient-to-tr from-[#C1502E40] to-transparent blur-2xl rounded-full animate-pulse pointer-events-none" />
</div>
</div>
))}

</div>
)}
Expand Down
Loading