Skip to content

(SP: 1) [Frontend] Disable quiz editor Save button when no changes made#356

Merged
ViktorSvertoka merged 2 commits intodevelopfrom
sl/feat/quiz
Feb 22, 2026
Merged

(SP: 1) [Frontend] Disable quiz editor Save button when no changes made#356
ViktorSvertoka merged 2 commits intodevelopfrom
sl/feat/quiz

Conversation

@LesiaUKR
Copy link
Collaborator

@LesiaUKR LesiaUKR commented Feb 22, 2026

  • disable quiz editor Save button when no changes made
  • eslint warnings fix
  • improve empty quiz category state to match Q&A pattern

Summary by CodeRabbit

  • New Features

    • Added new achievement badge icons (Code, Crown, GitHub Logo, Lightning, Star).
  • Improvements

    • Save button in the question editor now disables when there are no unsaved changes.
    • Quiz list “no quizzes” message updated to a multi-line, friendlier notice and now displays as a multi-line animated block with increased spacing.
  • Style & Refactoring

    • Import ordering and code organization tidied across multiple components.

@vercel
Copy link
Contributor

vercel bot commented Feb 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
devlovers-net Ready Ready Preview, Comment Feb 22, 2026 7:08pm

@netlify
Copy link

netlify bot commented Feb 22, 2026

Deploy Preview for develop-devlovers ready!

Name Link
🔨 Latest commit 9a22eed
🔍 Latest deploy log https://app.netlify.com/projects/develop-devlovers/deploys/699b53bec1c89d00084294d3
😎 Deploy Preview https://deploy-preview-356--develop-devlovers.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 22, 2026

📝 Walkthrough

Walkthrough

Reorders imports across many frontend files, adds a required csrfToken prop to DeleteQuizButton, tweaks QuestionEditor Save-button disabled logic, expands AchievementBadge icon set, and replaces the QuizzesSection empty-state with a multi-line animated block plus updated i18n messages.

Changes

Cohort / File(s) Summary
Admin Pages
frontend/app/[locale]/admin/page.tsx, frontend/app/[locale]/admin/quiz/[id]/page.tsx
Import order standardized; no behavior changes.
Admin Quiz Components
frontend/components/admin/quiz/CreateQuizForm.tsx, frontend/components/admin/quiz/DeleteQuizButton.tsx, frontend/components/admin/quiz/QuestionEditor.tsx, frontend/components/admin/quiz/QuizListTable.tsx, frontend/components/admin/quiz/QuizStatusControls.tsx, frontend/components/admin/quiz/UploadMoreQuestions.tsx
Mostly import reordering; DeleteQuizButton interface now requires csrfToken: string; QuestionEditor adds lint suppression and disables Save when nothing is dirty.
Quizzes UI & i18n
frontend/components/quiz/QuizzesSection.tsx, frontend/messages/en.json, frontend/messages/pl.json, frontend/messages/uk.json
Replaces single-line no-quizzes placeholder with a multiline, staggered animated block and increases container padding; updates corresponding translation strings to multi-line content.
Dashboard Components
frontend/components/dashboard/AchievementBadge.tsx
Adds several icons (Code, Crown, GithubLogo, Lightning, Star) to ICON_MAP and adjusts imports/types; no public signature change.
Home Components
frontend/components/home/FlipCardQA.tsx, frontend/components/home/InteractiveCTAButton.tsx
Reordered React hook imports; no functional changes.
DB / Lib / Misc
frontend/db/queries/quizzes/admin-quiz.ts, frontend/db/seed-questions.ts, frontend/lib/quiz/quiz-answers-redis.ts
Import order/type-import ordering changes; no logic or API changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • AM1007
  • ViktorSvertoka

Poem

🐰
Hopped through imports, neat and spry,
Added icons, waved bugs goodbye,
A token asked for, Save now wise,
New lines appear — a sweet surprise,
I nibble keys and celebrate the ties.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: disabling the Save button when no changes are made, which is confirmed by the QuestionEditor.tsx modification and is the primary feature change in the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sl/feat/quiz

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
frontend/components/quiz/QuizzesSection.tsx (1)

111-136: Extract lines above the map to eliminate the IIFE and redundant per-category computation.

t('noQuizzes') returns the same string for every category iteration. Computing lines once outside categoryData.map() avoids the repeated call and removes the inline IIFE, which is an unusual pattern in JSX.

♻️ Proposed refactor
+  const noQuizzesLines = t('noQuizzes')
+    .split('\n')
+    .map(l => l.trim())
+    .filter(Boolean);
+
   return (
     <div className="w-full">
       ...
         {categoryData.map(category => {
           ...
           return (
             <TabsContent key={category.slug} value={category.slug}>
               {categoryQuizzes.length > 0 ? (
                 ...
               ) : (
                 <div className="py-20 text-center">
-                  {(() => {
-                    const lines = t('noQuizzes')
-                      .split('\n')
-                      .map(l => l.trim())
-                      .filter(Boolean);
-                    return (
-                      <>
-                        {lines[0] && (
+                        {noQuizzesLines[0] && (
                           <p className="motion-safe:animate-fade-up text-lg font-semibold text-gray-900 motion-reduce:opacity-100 dark:text-white">
-                            {lines[0]}
+                            {noQuizzesLines[0]}
                           </p>
                         )}
-                        {lines[1] && (
+                        {noQuizzesLines[1] && (
                           <p className="motion-safe:animate-fade-up mt-2 text-gray-400 motion-safe:[animation-delay:150ms] motion-reduce:opacity-100 dark:text-gray-300">
-                            {lines[1]}
+                            {noQuizzesLines[1]}
                           </p>
                         )}
-                        {lines[2] && (
+                        {noQuizzesLines[2] && (
                           <p className="motion-safe:animate-fade-up mt-1 text-gray-500 motion-safe:[animation-delay:300ms] motion-reduce:opacity-100 dark:text-gray-400">
-                            {lines[2]}
+                            {noQuizzesLines[2]}
                           </p>
                         )}
-                      </>
-                    );
-                  })()}
                 </div>
               )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/components/quiz/QuizzesSection.tsx` around lines 111 - 136, The JSX
contains an IIFE that computes "lines" from t('noQuizzes') per render/iteration;
extract that computation out of the inline function and the per-category render
so it's computed once. Concretely, in QuizzesSection (the component rendering
the category list), compute const lines = t('noQuizzes').split('\n').map(l =>
l.trim()).filter(Boolean) once above where you call categoryData.map(...) and
then replace the IIFE with JSX that references lines[0], lines[1], lines[2]
directly; remove the anonymous self-invoking function to eliminate redundant
t('noQuizzes') calls and simplify the markup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/components/quiz/QuizzesSection.tsx`:
- Around line 111-136: The JSX contains an IIFE that computes "lines" from
t('noQuizzes') per render/iteration; extract that computation out of the inline
function and the per-category render so it's computed once. Concretely, in
QuizzesSection (the component rendering the category list), compute const lines
= t('noQuizzes').split('\n').map(l => l.trim()).filter(Boolean) once above where
you call categoryData.map(...) and then replace the IIFE with JSX that
references lines[0], lines[1], lines[2] directly; remove the anonymous
self-invoking function to eliminate redundant t('noQuizzes') calls and simplify
the markup.

@ViktorSvertoka ViktorSvertoka merged commit cc6f39c into develop Feb 22, 2026
11 checks passed
@ViktorSvertoka ViktorSvertoka deleted the sl/feat/quiz branch February 22, 2026 19:29
@LesiaUKR LesiaUKR restored the sl/feat/quiz branch February 22, 2026 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants