Skip to content

(SP: 3) [Frontend] Fix quiz timer on language switch + seed Angular/Vue/Node quizzes#135

Merged
ViktorSvertoka merged 1 commit into
developfrom
sl/feat/quiz
Jan 13, 2026
Merged

(SP: 3) [Frontend] Fix quiz timer on language switch + seed Angular/Vue/Node quizzes#135
ViktorSvertoka merged 1 commit into
developfrom
sl/feat/quiz

Conversation

@LesiaUKR
Copy link
Copy Markdown
Collaborator

@LesiaUKR LesiaUKR commented Jan 13, 2026

Week 5
Closes #133
Closes #134

Summary

  • Fix timer continuing correctly after language switch during quiz
  • Add retry logic for answer verification API calls
  • Add new quiz content for Angular, Vue.js, and Node.js categories (40 questions each)

Test plan

  • Start quiz, switch language mid-quiz -> timer should continue from where it left off
  • Verify answer with slow network -> should retry and show toast
  • Complete quiz as guest with timeout -> should show retry buttons, not login prompt
  • Check new quizzes appear in Angular, Vue, Node.js categories

Summary by CodeRabbit

  • New Features

    • Enhanced countdown timer with improved time tracking
    • Improved answer verification with automatic retry mechanism and user feedback
    • Added new quiz content: Angular Advanced, Node.js, and Vue.js frameworks with 40 questions each
    • Multi-language support (Ukrainian, English, Polish) across all new quizzes
  • Bug Fixes

    • Better handling of incomplete quizzes in results display
  • UI/UX

    • Added new "accent" button variant for improved visual hierarchy
    • Added toast notifications for answer verification failures and retries

✏️ Tip: You can customize this high-level summary in your review settings.

- Fix timer restart on language switch (use startedAt prop)
- Fix progress bar initial state calculation
- Add answer verification retry with toast notifications
- Hide score display for incomplete quizzes
- Fix guest message condition for incomplete results
- Add Button accent variant (prepared for future use)
- Reorder categories: Next.js before Angular
- Add seed quizzes: Angular, Vue, Node.js (40 questions each)
@netlify
Copy link
Copy Markdown

netlify Bot commented Jan 13, 2026

Deploy Preview for develop-devlovers ready!

Name Link
🔨 Latest commit 8585ccb
🔍 Latest deploy log https://app.netlify.com/projects/develop-devlovers/deploys/6966a4c24fa6860008ecd1b8
😎 Deploy Preview https://deploy-preview-135--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
Copy Markdown
Contributor

coderabbitai Bot commented Jan 13, 2026

📝 Walkthrough

Walkthrough

This PR fixes timer restart issues on language switching during quizzes by passing a startedAt timestamp to CountdownTimer, implements answer verification with retry logic, adds an accent button variant, reorders Angular/Next.js categories, expands quiz content with comprehensive multi-language seed scripts and question datasets for Angular, Node.js, and Vue, and includes localization updates for verification messaging.

Changes

Cohort / File(s) Summary
Timer & Quiz State Management
frontend/components/quiz/CountdownTimer.tsx, frontend/components/quiz/QuizContainer.tsx, frontend/components/quiz/QuizResult.tsx
Added startedAt prop to CountdownTimer to fix timer restart on language switch; threaded timestamp through endTime calculation. Implemented answer verification API integration with retry logic (single retry on failure) and toast notifications in QuizContainer. Updated QuizResult to conditionally show login prompt only for incomplete guest quizzes.
UI Styling & Components
frontend/components/ui/button.tsx
Extended Button variant union to include 'accent' with corresponding styling (bg-accent text-accent-foreground hover:bg-accent/90).
Localization
frontend/messages/en.json, frontend/messages/pl.json, frontend/messages/uk.json
Added verification status messages (verifyRetry, verifyFailed) under quiz.question for retry and failure scenarios across all three language files.
Quiz Category Data
frontend/data/category.ts
Swapped positions of Angular and Next.js entries at display order 6 and 8, updating associated slugs and labels while preserving order metadata.
Angular Quiz Seeds & Data
frontend/db/seed-quiz-angular.ts, json/quizzes/angular/beginner_medium/seed-quiz-angular.ts, json/quizzes/angular/beginner_medium/angular-quiz-part{1..4}.json, frontend/db/seed-quiz-angular-advanced.ts, json/quizzes/angular/advanced/seed-quiz-angular-advanced.ts, json/quizzes/angular/advanced/angular-advanced-quiz-part{1..4}.json
Added comprehensive multi-language (uk/en/pl) Angular quiz seed scripts handling quiz creation/updates with attempt validation, plus 8 JSON data files (4 beginner/medium, 4 advanced) containing 40 beginner questions and 40 advanced questions each.
Node.js Quiz Seeds & Data
frontend/db/seed-quiz-nodejs.ts, json/quizzes/node/beginner_medium/seed-quiz-nodejs-fundamentals.ts, json/quizzes/node/beginner_medium/nodejs-quiz-part{1..4}.json, frontend/db/seed-quiz-nodejs-advanced.ts, json/quizzes/node/advanced/seed-quiz-nodejs-advanced.ts, json/quizzes/node/advanced/nodejs-advanced-quiz-part{1..4}.json
Added multi-language Node.js quiz seed scripts (beginner and advanced tiers) with duplicate-prevention and translation management, plus 8 JSON data files containing 40 beginner and 40 advanced questions.
Vue Quiz Seeds & Data
frontend/db/seed-quiz-vue.ts, json/quizzes/vue/beginner_medium/seed-quiz-vue.ts, json/quizzes/vue/beginner_medium/vue-quiz-part{1..4}.json
Added Vue.js quiz seed script with multi-locale support, plus 4 JSON data files containing 40 beginner/medium level Vue questions.
Git Configuration
.gitignore
Added tmpclaude-* pattern to ignore temporary files/directories with that prefix.

Sequence Diagram(s)

sequenceDiagram
    participant User as User (Quiz UI)
    participant QuizContainer as QuizContainer
    participant API as /api/quiz/verify-answer
    participant Database as Database
    
    User->>QuizContainer: Submit answer
    QuizContainer->>QuizContainer: Set isVerifyingAnswer = true
    QuizContainer->>API: POST verify-answer request
    
    alt Verification Succeeds
        API->>Database: Check answer correctness
        Database-->>API: Correct/Incorrect result
        API-->>QuizContainer: 200 OK {ok: true, isCorrect: boolean}
        QuizContainer->>QuizContainer: Dispatch ANSWER_SELECTED
        QuizContainer->>User: Display result & next button
    else Verification Fails (Attempt 1)
        API-->>QuizContainer: Error or invalid response
        QuizContainer->>User: Show toast "Retrying answer verification..."
        QuizContainer->>QuizContainer: Wait 500ms
        QuizContainer->>API: POST verify-answer request (Retry)
        
        alt Retry Succeeds
            API-->>QuizContainer: 200 OK {ok: true, isCorrect: boolean}
            QuizContainer->>QuizContainer: Dispatch ANSWER_SELECTED
            QuizContainer->>User: Display result & next button
        else Retry Fails
            API-->>QuizContainer: Error or invalid response
            QuizContainer->>User: Show toast "Failed to verify the answer. Please try again."
            QuizContainer->>QuizContainer: Set isVerifyingAnswer = false
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • PR #131: Implements the answer verification API endpoint and initial quiz submission flow that this PR builds upon with retry logic and enhanced error handling.
  • PR #89: Added CountdownTimer component and timeLimitSeconds integration to QuizContainer; this PR extends it with the startedAt prop for timer persistence across language switches.
  • PR #78: Modified the category data structure and quiz categorization that this PR reorders with Angular/Next.js position swap.

Suggested reviewers

  • AM1007
  • ViktorSvertoka

🐰 Hops through quiz questions with glee,
Timer keeps ticking, as it should be,
Languages swap but the time stays true,
Verify and retry—the quiz runs through,
With seed scripts blooming from every land,

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Most changes align with objectives, but several modifications extend beyond the linked issue scope: quiz content seeding (Angular/Vue/Node.js), button accent variant, category reordering, answer verification retry logic with toast notifications, and additional UI/UX adjustments to QuizResult. Review and document scope of new quiz seeding, retry logic, and UI changes. Ensure these changes are intentional and not accidentally included—they may require separate issues or PR descriptions if not previously approved.
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 (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: fixing quiz timer on language switch and seeding new quizzes for Angular/Vue/Node, which are the primary objectives of this PR.
Linked Issues check ✅ Passed The PR successfully implements all requirements from issue #133 [133]: CountdownTimer accepts startedAt prop [133], endTime calculation uses startedAt [133], initial remainingSeconds fixed [133], QuizContainer passes startedAt to CountdownTimer [133], and QuizResult shows retry/back buttons for incomplete quizzes [133].
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing touches
  • 📝 Generate docstrings

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
Copy Markdown
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.

Actionable comments posted: 16

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/components/quiz/QuizResult.tsx (1)

37-44: Hardcoded Ukrainian strings break internationalization.

The incomplete quiz message uses hardcoded Ukrainian text instead of translation keys. This means English and Polish users will see Ukrainian text when their quiz times out with partial answers.

Compare with the other branches that correctly use t('timeUp.title') and t('timeUp.message').

🌐 Proposed fix using translation keys
     if (isIncomplete && answeredCount > 0) {
     return {
       emoji: '⏱️',
-      title: 'Час вийшов',
-      message: `Ви відповіли на ${answeredCount} з ${total} питань. Результат не зараховано.`,
+      title: t('timeUp.title'),
+      message: t('incompleteMessage', { answered: answeredCount, total }),
       color: 'text-orange-600 dark:text-orange-400',
     };
   }

You'll need to add the incompleteMessage key to your translation files (en.json, uk.json, pl.json) with appropriate interpolation.

frontend/components/quiz/QuizContainer.tsx (1)

60-77: Wrap switch case declaration in a block to prevent scope leakage.

The answersWithoutThisQuestion const declaration inside the switch case can be accessed by other cases, which is a common source of bugs. Per static analysis, wrap it in a block.

🔧 Suggested fix
     case 'ANSWER_SELECTED':
+    {
       const answersWithoutThisQuestion = state.answers.filter(
         a => a.questionId !== action.payload.questionId
       );
       return {
         ...state,
         selectedAnswerId: action.payload.answerId,
         questionStatus: 'revealed',
         answers: [
           ...answersWithoutThisQuestion,
           {
             questionId: action.payload.questionId,
             selectedAnswerId: action.payload.answerId,
             isCorrect: action.payload.isCorrect,
             answeredAt: new Date(),
           },
         ],
       };
+    }
🤖 Fix all issues with AI agents
In @frontend/db/seed-quiz-angular-advanced.ts:
- Around line 192-194: The usage strings printed for running the script are
incorrect; update the three console.log messages that currently reference
"db/seeds/seed-quiz-angular-advanced.ts" to the actual path
"db/seed-quiz-angular-advanced.ts" (the console.log calls in this file that
print Usage, Example, and Or upload all) so the CLI examples match the file
location.

In @frontend/db/seed-quiz-angular.ts:
- Around line 190-195: Update the usage/help text in the argument-check branch
so the printed path matches the actual file location; replace occurrences of
"db/seeds/seed-quiz-angular.ts" with "frontend/db/seed-quiz-angular.ts" in the
console.log/console.error block (the code that checks partArg in
seed-quiz-angular.ts) so the usage, example and "upload all" messages point to
the correct path.

In @frontend/db/seed-quiz-nodejs.ts:
- Around line 190-195: The usage/help messages printed in the if (!partArg)
branch reference the wrong filename/path; update the three console.log lines
inside that block (the usage & example lines shown in the seed check) to
reference the actual script name frontend/db/seed-quiz-nodejs.ts (e.g., "Usage:
npx tsx frontend/db/seed-quiz-nodejs.ts <part-number>", "Example: npx tsx
frontend/db/seed-quiz-nodejs.ts 1", and the "all" variant), leaving the rest of
the logic (process.exit(1)) unchanged so the message matches the real file and
invocation.

In @json/quizzes/angular/advanced/seed-quiz-angular-advanced.ts:
- Around line 186-191: The usage/help messages printed when partArg is missing
reference the wrong file path; update the console.log strings that currently
show "db/seeds/seed-quiz-angular-advanced.ts" to the actual script path used
here (the current file name used in the code: seed-quiz-angular-advanced.ts
under its package), e.g. change the usage and example lines to reflect
"json/quizzes/angular/advanced/seed-quiz-angular-advanced.ts" (or adjust to a
canonical invocation your project uses), or alternatively move the file to match
the printed path—ensure the console.log messages and example match the real
location so the usage is accurate.
- Around line 1-14: The seed file's imports (db, categories, quizzes,
quizTranslations, quizQuestions, quizQuestionContent, quizAnswers,
quizAnswerTranslations, quizAttempts) are resolving incorrectly because the file
is in json/quizzes/angular/advanced; either move the file into the same
directory as the DB code (so existing imports work) or change the import
statements to import the db instance and schema symbols from the real frontend
DB module locations; update the import sources for "db" and the "./schema/*"
modules to point at the modules that actually export those symbols so the named
imports (db, categories, quizzes, quizTranslations, quizQuestions,
quizQuestionContent, quizAnswers, quizAnswerTranslations, quizAttempts) resolve
correctly.
- Around line 64-68: The loadQuestions function uses the wrong base folder;
update the path creation in loadQuestions to point to the actual JSON location
by joining process.cwd() with 'json', 'quizzes', 'angular', 'advanced' and the
file name `angular-advanced-quiz-part${partNumber}.json` so loadQuestions reads
from the correct JSON files.

In @json/quizzes/angular/beginner_medium/seed-quiz-angular.ts:
- Around line 64-68: The loadQuestions function is using join(process.cwd(),
'data', ...) directly; replace that with the same projectRoot detection pattern
used in other seed scripts: determine projectRoot by checking filesystem
existence with existsSync (imported from 'fs'), set projectRoot to the detected
path, then use join(projectRoot, 'data', `angular-quiz-part${partNumber}.json`)
to build partPath and read the file; update loadQuestions to reference
projectRoot (same variable name and detection logic as in seed-quiz-vue.ts /
seed-quiz-nodejs-advanced.ts) so the data path resolution is consistent.
- Around line 1-14: This duplicate seed file is outdated and will break due to
incorrect relative imports and hardcoded paths; either delete
json/quizzes/angular/beginner_medium/seed-quiz-angular.ts or sync it with
frontend/db/seed-quiz-angular.ts by replacing its imports and path logic: update
the import list to include existsSync from 'fs', change './index' and
'./schema/...' imports to the same module paths used in frontend/db (or use
absolute/projectRoot detection like the working file) and replace
join(process.cwd(), 'data', ...) with the projectRoot detection logic used in
the canonical seed (ensure functions/consts like projectRoot, readFileSync
usage, and the same db/schema references — quizzes, quizTranslations,
quizQuestions, quizQuestionContent, quizAnswers, quizAnswerTranslations,
quizAttempts — match the frontend version).

In @json/quizzes/node/advanced/seed-quiz-nodejs-advanced.ts:
- Around line 186-191: Update the CLI usage strings so they reflect the actual
file location instead of db/seeds/...; replace the three console.log usages in
the block that checks partArg (the lines using 'Usage: npx tsx
db/seeds/seed-quiz-nodejs-advanced.ts <part-number>' and the example and "upload
all" lines) to reference the real path
'json/quizzes/node/advanced/seed-quiz-nodejs-advanced.ts' (or the finalized
location) so the messages shown when partArg is missing are accurate.
- Around line 64-68: The path construction in loadQuestions is wrong: update the
partPath used in loadQuestions to point to the actual JSON directory
(json/quizzes/node/advanced) instead of data; locate the partPath variable in
the loadQuestions function and change the join(...) call so it builds
process.cwd(), 'json', 'quizzes', 'node', 'advanced',
`nodejs-advanced-quiz-part${partNumber}.json` ensuring the filename format
matches nodejs-advanced-quiz-part{n}.json.
- Around line 1-14: The seed script is in the wrong directory and will break its
relative imports; move seed-quiz-nodejs-advanced.ts into the frontend/db/
directory alongside the other seed scripts so its existing relative imports
(import { db } from './index'; import { categories } from './schema/categories';
import { ... } from './schema/quiz';) resolve correctly, or if you must keep the
file in json/quizzes/, update the import paths to point to the actual db module
locations (e.g., adjust './index' and './schema/...' to the correct relative
path into frontend/db/), and re-run the provided verification commands to
confirm all seed scripts live under frontend/db/.

In @json/quizzes/node/beginner_medium/seed-quiz-nodejs-fundamentals.ts:
- Around line 64-68: The loadQuestions function uses process.cwd() and lacks a
file existence check; change it to use the same projectRoot detection pattern as
sibling seed scripts (compute projectRoot, then build the path under
json/quizzes/node/beginner_medium or the canonical directory used by other
scripts) and call existsSync to verify the file exists before readFileSync; if
the file is missing, throw or log a clear error. Update references inside
loadQuestions (function name) and local variables (partPath, partData)
accordingly so the path resolution and existence check match the other seed
scripts.
- Around line 1-14: The imports at the top (db, categories, quizzes,
quizTranslations, quizQuestions, quizQuestionContent, quizAnswers,
quizAnswerTranslations, quizAttempts) are pointing to non-existent relative
paths (e.g., './index' and './schema/categories'); update those import
specifiers to the correct module locations under the actual frontend/db package
(replace './index' and './schema/...' with the appropriate 'frontend/db/...'
module paths used by the project) so symbols like db and categories resolve at
runtime, and change the data file loading (currently using join(process.cwd(),
'data', ...)) to load from the seed file's directory (use the script's directory
as the base, e.g., using __dirname or path.join(dirname,
'nodejs-quiz-part1.json')) so readFileSync reads the local JSON files like
nodejs-quiz-part1.json successfully.

In @json/quizzes/vue/beginner_medium/seed-quiz-vue.ts:
- Around line 186-189: Update the usage/help messages currently printed by the
script (the console.error and console.log calls) to reference the actual path
and invocation for this file (json/quizzes/vue/beginner_medium/seed-quiz-vue.ts)
instead of db/seeds/seed-quiz-vue.ts; locate the console.error('Error: Please
specify which part to upload') and the following console.log(...) lines and
change their strings to show the correct path and examples (e.g., npx tsx
json/quizzes/vue/beginner_medium/seed-quiz-vue.ts <part-number> and
corresponding example for "all").
- Around line 64-68: The loadQuestions function currently builds partPath using
process.cwd() which can point to the wrong working directory; change it to
resolve the JSON files relative to this script by using __dirname (i.e. compute
partPath with path.join(__dirname, `vue-quiz-part${partNumber}.json`) or
join(__dirname, 'json/quizzes/vue/beginner_medium', ... ) depending on where the
files live) so loadQuestions reads the files next to the script; if this repo
uses ES modules, derive __dirname via fileURLToPath(import.meta.url) and dirname
before using it.
🧹 Nitpick comments (8)
json/quizzes/vue/beginner_medium/seed-quiz-vue.ts (1)

211-211: Hardcoded answer count may be misleading.

The summary assumes exactly 4 answers per question. Consider calculating the actual total dynamically if answer counts vary.

Suggested fix

Track actual answer count during seeding:

       let totalQuestions = 0;
+      let totalAnswers = 0;

       for (let i = 1; i <= 4; i++) {
         const questions = await loadQuestions(i);
         await seedQuestions(questions, quizId, i);
         totalQuestions += questions.length;
+        totalAnswers += questions.reduce((sum, q) => sum + q.answers.length, 0);
       }

       console.log('\nAll parts seeded successfully!');
       console.log(`   - 1 quiz with ${LOCALES.length} translations`);
       console.log(`   - ${totalQuestions} questions total`);
-      console.log(`   - ${totalQuestions * 4} answers with ${LOCALES.length} translations each`);
+      console.log(`   - ${totalAnswers} answers with ${LOCALES.length} translations each`);
frontend/db/seed-quiz-angular-advanced.ts (2)

2-2: Minor formatting: Missing space after comma in import.

Suggested fix
-import { readFileSync,existsSync } from 'fs';
+import { readFileSync, existsSync } from 'fs';

186-237: Consider wrapping seed operations in a transaction.

If the seeding process fails midway (e.g., during seedQuestions), partial data may remain in the database, leading to an inconsistent state. Wrapping the quiz creation and question seeding in a transaction would ensure atomicity—either all data is committed or none.

This is a recommended improvement for robustness, especially when seeding multiple parts with the all argument.

json/quizzes/angular/advanced/seed-quiz-angular-advanced.ts (1)

96-118: Consider wrapping delete/update/insert operations in a transaction.

The sequence of deleting questions/translations, updating the quiz, and inserting new translations is not atomic. If the script fails mid-way (e.g., after line 97 but before line 115), data could be left in an inconsistent state.

Suggested approach using db.transaction
   if (existing) {
-    const existingAttempt = await db.query.quizAttempts.findFirst({
-      where: eq(quizAttempts.quizId, existing.id),
-    });
-    if (existingAttempt) {
-      throw new Error(`Quiz ${QUIZ_METADATA.slug} has existing attempts. Aborting to avoid data loss.`);
-    }
-
-    await db.delete(quizQuestions).where(eq(quizQuestions.quizId, existing.id));
-    await db.delete(quizTranslations).where(eq(quizTranslations.quizId, existing.id));
-    await db.update(quizzes).set({
-      ...
-    }).where(eq(quizzes.id, existing.id));
-
-    const quizId = existing.id;
-    for (const locale of LOCALES) {
-      await db.insert(quizTranslations).values({ ... });
-    }
-
-    return quizId;
+    return await db.transaction(async (tx) => {
+      const existingAttempt = await tx.query.quizAttempts.findFirst({
+        where: eq(quizAttempts.quizId, existing.id),
+      });
+      if (existingAttempt) {
+        throw new Error(`Quiz ${QUIZ_METADATA.slug} has existing attempts. Aborting to avoid data loss.`);
+      }
+
+      await tx.delete(quizQuestions).where(eq(quizQuestions.quizId, existing.id));
+      await tx.delete(quizTranslations).where(eq(quizTranslations.quizId, existing.id));
+      await tx.update(quizzes).set({ ... }).where(eq(quizzes.id, existing.id));
+
+      for (const locale of LOCALES) {
+        await tx.insert(quizTranslations).values({ ... });
+      }
+
+      return existing.id;
+    });
   }
frontend/db/seed-quiz-nodejs.ts (2)

100-122: Consider transaction wrapping for atomicity.

Same as noted for the Angular Advanced seed script: the delete/update/insert sequence for existing quizzes would benefit from transaction wrapping to prevent partial data states on failure.


145-184: Optional: Consider batch inserts for performance.

The current implementation makes individual INSERT calls for each question, locale content, answer, and answer translation. For 40 questions with 3 locales and ~4 answers each, this results in ~600+ individual DB operations.

Drizzle supports batch inserts that could reduce this significantly, though for a one-time seed script the current approach is acceptable.

frontend/db/seed-quiz-angular.ts (2)

100-122: Same transaction wrapping recommendation applies.

For consistency with the other seed scripts, consider wrapping the delete/update/insert sequence in a transaction.


16-62: Optional: Extract shared utilities to reduce duplication.

The type definitions (Locale, QuestionData, QuizPartData), helper functions (createExplanation), and core seeding logic (ensureQuizExists, seedQuestions) are nearly identical across all seed scripts (seed-quiz-angular.ts, seed-quiz-nodejs.ts, seed-quiz-angular-advanced.ts, etc.).

Consider extracting these into a shared seed-utils.ts module that exports:

  • Common types and interfaces
  • createExplanation helper
  • Generic ensureQuizExists(metadata, categorySlug) function
  • Generic seedQuestions(questions, quizId, partNumber) function

Each quiz-specific script would then only define its metadata and file paths.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32eedcc and 8585ccb.

📒 Files selected for processing (39)
  • .gitignore
  • frontend/components/quiz/CountdownTimer.tsx
  • frontend/components/quiz/QuizContainer.tsx
  • frontend/components/quiz/QuizResult.tsx
  • frontend/components/ui/button.tsx
  • frontend/data/category.ts
  • frontend/db/seed-quiz-angular-advanced.ts
  • frontend/db/seed-quiz-angular.ts
  • frontend/db/seed-quiz-nodejs-advanced.ts
  • frontend/db/seed-quiz-nodejs.ts
  • frontend/db/seed-quiz-vue.ts
  • frontend/messages/en.json
  • frontend/messages/pl.json
  • frontend/messages/uk.json
  • json/quizzes/angular/advanced/angular-advanced-quiz-part1.json
  • json/quizzes/angular/advanced/angular-advanced-quiz-part2.json
  • json/quizzes/angular/advanced/angular-advanced-quiz-part3.json
  • json/quizzes/angular/advanced/angular-advanced-quiz-part4.json
  • json/quizzes/angular/advanced/seed-quiz-angular-advanced.ts
  • json/quizzes/angular/beginner_medium/angular-quiz-part1.json
  • json/quizzes/angular/beginner_medium/angular-quiz-part2.json
  • json/quizzes/angular/beginner_medium/angular-quiz-part3.json
  • json/quizzes/angular/beginner_medium/angular-quiz-part4.json
  • json/quizzes/angular/beginner_medium/seed-quiz-angular.ts
  • json/quizzes/node/advanced/nodejs-advanced-quiz-part1.json
  • json/quizzes/node/advanced/nodejs-advanced-quiz-part2.json
  • json/quizzes/node/advanced/nodejs-advanced-quiz-part3.json
  • json/quizzes/node/advanced/nodejs-advanced-quiz-part4.json
  • json/quizzes/node/advanced/seed-quiz-nodejs-advanced.ts
  • json/quizzes/node/beginner_medium/nodejs-quiz-part1.json
  • json/quizzes/node/beginner_medium/nodejs-quiz-part2.json
  • json/quizzes/node/beginner_medium/nodejs-quiz-part3.json
  • json/quizzes/node/beginner_medium/nodejs-quiz-part4.json
  • json/quizzes/node/beginner_medium/seed-quiz-nodejs-fundamentals.ts
  • json/quizzes/vue/beginner_medium/seed-quiz-vue.ts
  • json/quizzes/vue/beginner_medium/vue-quiz-part1.json
  • json/quizzes/vue/beginner_medium/vue-quiz-part2.json
  • json/quizzes/vue/beginner_medium/vue-quiz-part3.json
  • json/quizzes/vue/beginner_medium/vue-quiz-part4.json
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-30T16:01:02.523Z
Learnt from: kryvosheyin
Repo: DevLoversTeam/devlovers.net PR: 88
File: frontend/drizzle/schema.ts:153-153
Timestamp: 2025-12-30T16:01:02.523Z
Learning: The file frontend/drizzle/schema.ts is a legacy file not used by Drizzle or the runtime. The canonical schemas live in frontend/db/schema/* as configured in drizzle-config.ts, and that's what migrations and runtime use.

Applied to files:

  • frontend/db/seed-quiz-nodejs.ts
  • frontend/db/seed-quiz-angular.ts
🧬 Code graph analysis (11)
frontend/db/seed-quiz-nodejs-advanced.ts (1)
frontend/db/index.ts (1)
  • db (37-37)
frontend/components/quiz/QuizResult.tsx (2)
frontend/db/seed-quiz-types.ts (2)
  • p (37-40)
  • t (42-48)
frontend/lib/utils.ts (1)
  • cn (4-6)
frontend/db/seed-quiz-angular-advanced.ts (1)
frontend/db/index.ts (1)
  • db (37-37)
frontend/db/seed-quiz-vue.ts (1)
frontend/db/index.ts (1)
  • db (37-37)
frontend/db/seed-quiz-nodejs.ts (2)
frontend/scripts/shop-janitor-restock-stale.mjs (1)
  • text (66-66)
frontend/db/index.ts (1)
  • db (37-37)
json/quizzes/vue/beginner_medium/seed-quiz-vue.ts (1)
frontend/db/index.ts (1)
  • db (37-37)
frontend/db/seed-quiz-angular.ts (1)
frontend/db/index.ts (1)
  • db (37-37)
json/quizzes/angular/advanced/seed-quiz-angular-advanced.ts (1)
frontend/db/index.ts (1)
  • db (37-37)
frontend/components/quiz/QuizContainer.tsx (3)
frontend/lib/quiz/quiz-session.ts (1)
  • QuizSessionData (4-17)
frontend/hooks/useQuizSession.ts (1)
  • useQuizSession (32-76)
frontend/components/ui/button.tsx (1)
  • Button (44-44)
json/quizzes/node/beginner_medium/seed-quiz-nodejs-fundamentals.ts (1)
frontend/db/index.ts (1)
  • db (37-37)
json/quizzes/angular/beginner_medium/seed-quiz-angular.ts (2)
frontend/scripts/shop-janitor-restock-stale.mjs (1)
  • text (66-66)
frontend/db/index.ts (1)
  • db (37-37)
🪛 Biome (2.1.2)
frontend/components/quiz/QuizContainer.tsx

[error] 61-63: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (47)
json/quizzes/vue/beginner_medium/seed-quiz-vue.ts (2)

16-58: LGTM!

Type definitions and quiz metadata are well-structured with proper locale support for all three languages.


140-179: LGTM!

The seeding logic correctly handles questions, translations, and answers with proper ordering and difficulty assignment.

.gitignore (1)

75-75: LGTM!

The tmpclaude-* ignore pattern is appropriate for preventing temporary generation artifacts from being committed.

json/quizzes/vue/beginner_medium/vue-quiz-part3.json (1)

1-434: LGTM!

The Vue quiz data file is well-structured with consistent JSON format. Each question has proper multilingual support (uk/en/pl), exactly one correct answer per question, and accurate technical content covering Vue Router, Vuex, Pinia, mixins, custom directives, provide/inject, Composition API, and ref vs reactive.

frontend/messages/uk.json (1)

99-101: LGTM!

The new localization keys verifyRetry and verifyFailed support the answer verification retry logic mentioned in the PR objectives. The Ukrainian translations are grammatically correct and follow the existing naming conventions.

json/quizzes/node/advanced/nodejs-advanced-quiz-part2.json (1)

1-434: LGTM!

The Node.js advanced quiz data file is well-structured with 10 questions (node-adv-q11 through node-adv-q20). Each question has proper multilingual support, exactly one correct answer, and covers relevant advanced Node.js topics including NestJS architecture, Koa.js middleware model, GraphQL, SSR/hydration, TypeScript benefits, and Twelve-Factor App principles.

Note: The AI summary incorrectly states "9 Node.js advanced quiz questions" when the file actually contains 10 questions.

json/quizzes/angular/advanced/angular-advanced-quiz-part4.json (1)

1-434: LGTM!

The Angular advanced quiz data file is well-structured with 10 questions (angular-adv-q31 through angular-adv-q40). Each question has proper multilingual support, exactly one correct answer, and covers relevant advanced Angular topics including Hydration, TransferState, SSR platform detection, routing parameters, Preloading Strategy, the inject() function, and Angular Signals (effect() and computed()).

json/quizzes/angular/beginner_medium/angular-quiz-part1.json (1)

1-434: LGTM!

The quiz data file is well-structured with consistent schema across all 10 questions. The Angular content is technically accurate, covering fundamental concepts like components, data binding types, directives, standalone components, and decorators. The multi-language translations (uk, en, pl) are consistently provided for questions, explanations, and all answer options.

json/quizzes/vue/beginner_medium/vue-quiz-part1.json (1)

1-434: LGTM!

The Vue.js quiz data is well-structured and technically accurate. Questions appropriately cover Vue 3 concepts including the Composition API references (createApp, onMounted), while also acknowledging Options API patterns. The difficulty progression from beginner to medium is reasonable, and all three language translations are consistently provided.

frontend/messages/pl.json (1)

99-102: LGTM!

The new localization keys verifyRetry and verifyFailed appropriately support the answer verification retry feature mentioned in the PR objectives. The Polish translations are grammatically correct and convey the intended messages for retry notification and failure scenarios.

json/quizzes/angular/advanced/angular-advanced-quiz-part1.json (1)

1-434: LGTM!

The advanced Angular quiz content is technically accurate and covers important intermediate-to-advanced concepts including lifecycle hooks order, view/content child queries, content projection, and form validators. The difficulty labels appropriately distinguish between medium and advanced questions. The lifecycle hook ordering in q10 is correctly stated.

json/quizzes/angular/beginner_medium/angular-quiz-part3.json (1)

1-434: LGTM!

The quiz data is technically accurate and covers important Angular concepts including reactive forms (FormArray), routing (router-outlet, lazy loading, Route Guards, ActivatedRoute), HTTP handling (HttpClient, catchError), and modern features (async pipe, Signals, change detection). The inclusion of Signals (q29) appropriately represents current Angular development practices.

frontend/data/category.ts (1)

18-20: LGTM!

The category reorder placing Next.js before Angular is consistent with the PR objectives. The displayOrder values correctly match their array positions.

frontend/messages/en.json (1)

99-101: LGTM!

The new translation keys for verification retry logic are clear and user-friendly. They align well with the PR's retry functionality for answer verification.

json/quizzes/node/advanced/nodejs-advanced-quiz-part4.json (1)

1-434: LGTM!

Well-structured quiz data with consistent format across all 10 questions. Each question has proper multilingual support (uk/en/pl), exactly one correct answer, and covers relevant advanced Node.js topics (IoT, MQTT, ML integration, Kubernetes scaling, secrets management, etc.).

json/quizzes/node/advanced/nodejs-advanced-quiz-part3.json (1)

1-434: LGTM!

Consistent quiz data structure with proper multilingual translations. The questions cover important advanced Node.js and DevOps topics (serverless architecture, cold start mitigation, CI/CD, session management, profiling tools, etc.) with accurate technical content.

frontend/components/quiz/CountdownTimer.tsx (3)

26-42: LGTM on the interval-based countdown logic.

The effect correctly uses endTime in its dependency array, ensuring the interval recalculates remaining time based on the stable quiz start time. Using a 100ms interval provides smooth UI updates while queueMicrotask(onTimeUp) properly defers the callback to avoid state updates during render.


44-57: Good handling of tab visibility changes.

The visibility change handler ensures the timer display syncs correctly when users return to the tab, preventing any visual discrepancy between displayed time and actual remaining time.


11-24: Well-implemented fix for the timer restart issue.

The introduction of startedAt prop elegantly solves the language-switch timer restart problem. By computing endTime from a stable startedAt timestamp rather than Date.now() at mount time, the timer now correctly maintains its remaining time across component remounts.

Key improvements:

  • endTime is now an absolute timestamp based on when the quiz actually started
  • Initial remainingSeconds correctly computes from endTime - Date.now()
  • Effects properly depend on endTime for consistency
  • QuizContainer correctly passes state.startedAt! to the component
json/quizzes/angular/advanced/angular-advanced-quiz-part3.json (1)

1-434: LGTM! Well-structured Angular advanced quiz questions.

The JSON structure is consistent with the expected schema for the seed scripts. Questions cover important Angular topics (NgRx, ChangeDetection, animations, DI). All translations (uk/en/pl) are present, and each question has exactly one correct answer.

Note: Some questions (q25, q26, q27, q29, q30) have difficulty: "medium" rather than "advanced". This appears intentional for a mixed-difficulty quiz, but verify this aligns with the quiz design expectations.

frontend/components/quiz/QuizResult.tsx (1)

93-117: Conditional rendering logic looks correct.

The changes properly implement the PR objectives:

  • Score/percentage/progress bar hidden when isIncomplete is true
  • Guest login prompt only shown when isGuest && !isIncomplete, so incomplete quizzes show retry/back buttons instead

The ternary at line 148 correctly routes:

  • Guest with completed quiz → login/signup buttons
  • Guest with incomplete quiz OR authenticated user → retry/back buttons

Also applies to: 148-181

json/quizzes/node/beginner_medium/nodejs-quiz-part3.json (1)

1-434: LGTM! Well-structured Node.js quiz questions.

The JSON structure is consistent and properly formatted. Questions cover essential Node.js topics (Express.js, middleware, security with helmet, error handling, ORMs, environment variables, JWT, EventEmitter). All translations are present and each question has exactly one correct answer with appropriate difficulty levels.

json/quizzes/angular/advanced/angular-advanced-quiz-part2.json (1)

1-434: LGTM! Well-structured Angular advanced quiz questions (part 2).

The JSON structure is consistent with the expected schema. Questions cover important Angular advanced topics including dependency injection decorators (@optional, @self, @SkipSelf, @Inject), RxJS subjects (Subject, BehaviorSubject, ReplaySubject), structural directives with ViewContainerRef, and routing guards. All translations are present and technically accurate.

json/quizzes/vue/beginner_medium/vue-quiz-part2.json (1)

1-434: LGTM! Well-structured Vue.js quiz data.

The quiz data file is properly structured with:

  • Consistent schema across all 10 questions (vue-q11 to vue-q20)
  • Complete multilingual support (uk, en, pl) for questions, explanations, and answers
  • Exactly one correct answer per question
  • Accurate Vue.js technical content covering core concepts (v-bind/v-model, computed properties, watchers, props, slots, emit)
json/quizzes/vue/beginner_medium/vue-quiz-part4.json (1)

1-434: LGTM! Comprehensive Vue.js quiz data for part 4.

The quiz data maintains structural consistency with other parts:

  • 10 questions (vue-q31 to vue-q40) with sequential ordering
  • Complete translations for all three locales
  • Covers advanced Vue.js topics (SFC, Vue 3 features, Teleport, Nuxt.js, transitions)
  • Correct answer marked for each question
json/quizzes/node/beginner_medium/nodejs-quiz-part4.json (1)

1-434: LGTM! Well-structured Node.js quiz data.

The quiz data is properly formatted with:

  • 10 questions (node-q31 to node-q40) covering production Node.js topics
  • Consistent schema matching other quiz files in the PR
  • Complete multilingual content (uk, en, pl)
  • Topics include testing (Jest), PM2, clustering, WebSockets, Docker, Worker Threads, and memory management
json/quizzes/node/advanced/nodejs-advanced-quiz-part1.json (1)

1-434: LGTM! Advanced Node.js quiz data with appropriate complexity.

The advanced quiz data is well-designed:

  • 10 questions (node-adv-q01 to node-adv-q10) with distinct ID pattern for the advanced category
  • Covers sophisticated topics: microservices (BFF, gRPC), event loop internals (nextTick vs setImmediate), security (CSP, brute-force protection), messaging systems (RabbitMQ, Kafka, ZeroMQ)
  • Consistent structure with other quiz files
  • Complete multilingual support
frontend/components/ui/button.tsx (1)

6-6: LGTM! New accent variant added correctly.

The variant type and styling are properly implemented. The accent CSS variables (--accent and --accent-foreground) are already defined in frontend/app/globals.css with appropriate light and dark theme values, as well as in the shop theme.

Note: The accent variant lacks an active: state, consistent with the secondary and outline variants. Only the primary variant defines an active state. Add one if you want consistent interactive feedback across all variants.

json/quizzes/angular/beginner_medium/angular-quiz-part2.json (1)

1-434: LGTM!

The Angular quiz part 2 data file is well-structured with consistent multilingual content (uk/en/pl). Each question has exactly one correct answer, appropriate difficulty levels (beginner/medium), and sequential ordering (q11-q20). The Angular technical content (decorators, services, DI, lifecycle hooks, pipes, forms) appears accurate.

json/quizzes/node/beginner_medium/nodejs-quiz-part2.json (1)

1-434: LGTM!

The Node.js quiz part 2 data file is well-structured with consistent multilingual content. Each question has exactly one correct answer, appropriate difficulty levels, and sequential ordering (q11-q20). The Node.js technical content (fs, path, Buffer, streams, error-first callbacks, Promises, async/await) is accurate.

json/quizzes/node/beginner_medium/nodejs-quiz-part1.json (1)

1-434: LGTM!

The Node.js quiz part 1 data file is well-structured with consistent multilingual content. Each question has exactly one correct answer, appropriate difficulty progression (beginner to medium), and sequential ordering (q01-q10). The foundational Node.js concepts (runtime, event loop, npm, package.json, libuv) are accurately covered.

json/quizzes/angular/beginner_medium/angular-quiz-part4.json (1)

1-434: LGTM!

The Angular quiz part 4 data file is well-structured with consistent multilingual content. Each question has exactly one correct answer, appropriate difficulty levels, and sequential ordering (q31-q40). The advanced Angular topics (ViewEncapsulation, BehaviorSubject, Zone.js/Signals, AOT/JIT, NgRx, SSR) are accurately covered with current best practices.

frontend/db/seed-quiz-angular-advanced.ts (1)

100-101: Cascade delete is properly configured—no action needed.

All child tables (quizQuestionContent, quizAnswers, quizAnswerTranslations) are correctly configured with onDelete: 'cascade' in the schema. When quizQuestions or quizTranslations are deleted, their child records will be automatically removed by the database, preventing orphaned data.

Likely an incorrect or invalid review comment.

json/quizzes/node/beginner_medium/seed-quiz-nodejs-fundamentals.ts (2)

70-139: Quiz upsert logic looks correct with proper safety checks.

The function properly:

  • Validates category existence before proceeding
  • Aborts if existing quiz has attempts (data protection)
  • Cleans up old questions/translations before re-seeding

141-233: Seeding logic is correct.

The question seeding and CLI handling are implemented correctly. Individual inserts are acceptable for seed scripts, though batch inserts could improve performance for large datasets.

frontend/db/seed-quiz-nodejs-advanced.ts (2)

64-72: Project root detection and file loading are correctly implemented.

The projectRoot detection pattern handles running the script from different directories, and the file path structure is consistent with other seed scripts.


74-243: Quiz existence check and seeding logic are well-implemented.

The script includes proper safeguards against data loss and handles all locales consistently.

frontend/db/seed-quiz-vue.ts (2)

1-72: Well-structured seed script following established patterns.

The Vue seed script correctly implements:

  • Project root detection for flexible execution
  • Proper import paths
  • Consistent data file path structure

74-243: Quiz management and seeding logic are correctly implemented.

The upsert logic with attempt protection and multi-locale support follows the established pattern consistently.

json/quizzes/angular/beginner_medium/seed-quiz-angular.ts (1)

70-239: Core seeding logic is correctly implemented.

The quiz existence check, data protection against existing attempts, and multi-locale seeding logic are all properly implemented.

frontend/components/quiz/QuizContainer.tsx (4)

177-186: Session restoration callback is correctly memoized.

The useCallback with empty dependencies is appropriate since dispatch from useReducer is stable across renders.


213-276: Answer verification with retry logic is well-implemented.

The implementation correctly:

  • Validates response structure (checks ok and isCorrect type)
  • Prevents concurrent verification with isVerifyingAnswer guard
  • Provides user feedback via toast on retry and failure
  • Uses finally to ensure state cleanup

476-486: Timer fix correctly passes startedAt to CountdownTimer.

The startedAt prop enables the timer to calculate the correct remaining time based on when the quiz actually started, fixing the language-switch timer restart issue mentioned in the PR objectives.

The non-null assertion is safe here since this code only executes when status === 'in_progress', which is set after START_QUIZ (which initializes startedAt).


427-429: Button change looks good.

The explicit size="md" prop is a reasonable addition for consistency.

frontend/db/seed-quiz-nodejs.ts (2)

1-14: LGTM - Imports and structure are correct.

The imports correctly resolve to frontend/db/index.ts and the schema modules from this location.


64-72: Good: Dynamic project root detection handles multiple working directories.

The existsSync check allows the script to run correctly whether invoked from the repository root or from the frontend/ directory.

frontend/db/seed-quiz-angular.ts (1)

1-72: LGTM - Structure and imports are correct.

The file follows the same correct patterns as seed-quiz-nodejs.ts with appropriate imports and project root detection.

Comment on lines +192 to +194
console.log('Usage: npx tsx db/seeds/seed-quiz-angular-advanced.ts <part-number>');
console.log('Example: npx tsx db/seeds/seed-quiz-angular-advanced.ts 1');
console.log('Or upload all: npx tsx db/seeds/seed-quiz-angular-advanced.ts all');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Usage message path is inconsistent with actual file location.

The usage examples reference db/seeds/seed-quiz-angular-advanced.ts, but based on the file path, the script is located at db/seed-quiz-angular-advanced.ts (without the seeds subdirectory).

Suggested fix
-    console.log('Usage: npx tsx db/seeds/seed-quiz-angular-advanced.ts <part-number>');
-    console.log('Example: npx tsx db/seeds/seed-quiz-angular-advanced.ts 1');
-    console.log('Or upload all: npx tsx db/seeds/seed-quiz-angular-advanced.ts all');
+    console.log('Usage: npx tsx db/seed-quiz-angular-advanced.ts <part-number>');
+    console.log('Example: npx tsx db/seed-quiz-angular-advanced.ts 1');
+    console.log('Or upload all: npx tsx db/seed-quiz-angular-advanced.ts all');
📝 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
console.log('Usage: npx tsx db/seeds/seed-quiz-angular-advanced.ts <part-number>');
console.log('Example: npx tsx db/seeds/seed-quiz-angular-advanced.ts 1');
console.log('Or upload all: npx tsx db/seeds/seed-quiz-angular-advanced.ts all');
console.log('Usage: npx tsx db/seed-quiz-angular-advanced.ts <part-number>');
console.log('Example: npx tsx db/seed-quiz-angular-advanced.ts 1');
console.log('Or upload all: npx tsx db/seed-quiz-angular-advanced.ts all');
🤖 Prompt for AI Agents
In @frontend/db/seed-quiz-angular-advanced.ts around lines 192 - 194, The usage
strings printed for running the script are incorrect; update the three
console.log messages that currently reference
"db/seeds/seed-quiz-angular-advanced.ts" to the actual path
"db/seed-quiz-angular-advanced.ts" (the console.log calls in this file that
print Usage, Example, and Or upload all) so the CLI examples match the file
location.

Comment on lines +190 to +195
if (!partArg) {
console.error('Error: Please specify which part to upload');
console.log('Usage: npx tsx db/seeds/seed-quiz-angular.ts <part-number>');
console.log('Example: npx tsx db/seeds/seed-quiz-angular.ts 1');
console.log('Or upload all: npx tsx db/seeds/seed-quiz-angular.ts all');
process.exit(1);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Usage message path should be updated.

The path references db/seeds/seed-quiz-angular.ts but the file is at frontend/db/seed-quiz-angular.ts.

Suggested fix
-    console.log('Usage: npx tsx db/seeds/seed-quiz-angular.ts <part-number>');
-    console.log('Example: npx tsx db/seeds/seed-quiz-angular.ts 1');
-    console.log('Or upload all: npx tsx db/seeds/seed-quiz-angular.ts all');
+    console.log('Usage: npx tsx frontend/db/seed-quiz-angular.ts <part-number>');
+    console.log('Example: npx tsx frontend/db/seed-quiz-angular.ts 1');
+    console.log('Or upload all: npx tsx frontend/db/seed-quiz-angular.ts all');
📝 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
if (!partArg) {
console.error('Error: Please specify which part to upload');
console.log('Usage: npx tsx db/seeds/seed-quiz-angular.ts <part-number>');
console.log('Example: npx tsx db/seeds/seed-quiz-angular.ts 1');
console.log('Or upload all: npx tsx db/seeds/seed-quiz-angular.ts all');
process.exit(1);
if (!partArg) {
console.error('Error: Please specify which part to upload');
console.log('Usage: npx tsx frontend/db/seed-quiz-angular.ts <part-number>');
console.log('Example: npx tsx frontend/db/seed-quiz-angular.ts 1');
console.log('Or upload all: npx tsx frontend/db/seed-quiz-angular.ts all');
process.exit(1);
🤖 Prompt for AI Agents
In @frontend/db/seed-quiz-angular.ts around lines 190 - 195, Update the
usage/help text in the argument-check branch so the printed path matches the
actual file location; replace occurrences of "db/seeds/seed-quiz-angular.ts"
with "frontend/db/seed-quiz-angular.ts" in the console.log/console.error block
(the code that checks partArg in seed-quiz-angular.ts) so the usage, example and
"upload all" messages point to the correct path.

Comment on lines +190 to +195
if (!partArg) {
console.error('Error: Please specify which part to upload');
console.log('Usage: npx tsx db/seeds/seed-quiz-nodejs-fundamentals.ts <part-number>');
console.log('Example: npx tsx db/seeds/seed-quiz-nodejs-fundamentals.ts 1');
console.log('Or upload all: npx tsx db/seeds/seed-quiz-nodejs-fundamentals.ts all');
process.exit(1);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Usage message references incorrect path and filename.

The usage examples show db/seeds/seed-quiz-nodejs-fundamentals.ts, but the actual file is frontend/db/seed-quiz-nodejs.ts. Update to match the actual location.

Suggested fix
-    console.log('Usage: npx tsx db/seeds/seed-quiz-nodejs-fundamentals.ts <part-number>');
-    console.log('Example: npx tsx db/seeds/seed-quiz-nodejs-fundamentals.ts 1');
-    console.log('Or upload all: npx tsx db/seeds/seed-quiz-nodejs-fundamentals.ts all');
+    console.log('Usage: npx tsx frontend/db/seed-quiz-nodejs.ts <part-number>');
+    console.log('Example: npx tsx frontend/db/seed-quiz-nodejs.ts 1');
+    console.log('Or upload all: npx tsx frontend/db/seed-quiz-nodejs.ts all');
📝 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
if (!partArg) {
console.error('Error: Please specify which part to upload');
console.log('Usage: npx tsx db/seeds/seed-quiz-nodejs-fundamentals.ts <part-number>');
console.log('Example: npx tsx db/seeds/seed-quiz-nodejs-fundamentals.ts 1');
console.log('Or upload all: npx tsx db/seeds/seed-quiz-nodejs-fundamentals.ts all');
process.exit(1);
if (!partArg) {
console.error('Error: Please specify which part to upload');
console.log('Usage: npx tsx frontend/db/seed-quiz-nodejs.ts <part-number>');
console.log('Example: npx tsx frontend/db/seed-quiz-nodejs.ts 1');
console.log('Or upload all: npx tsx frontend/db/seed-quiz-nodejs.ts all');
process.exit(1);
🤖 Prompt for AI Agents
In @frontend/db/seed-quiz-nodejs.ts around lines 190 - 195, The usage/help
messages printed in the if (!partArg) branch reference the wrong filename/path;
update the three console.log lines inside that block (the usage & example lines
shown in the seed check) to reference the actual script name
frontend/db/seed-quiz-nodejs.ts (e.g., "Usage: npx tsx
frontend/db/seed-quiz-nodejs.ts <part-number>", "Example: npx tsx
frontend/db/seed-quiz-nodejs.ts 1", and the "all" variant), leaving the rest of
the logic (process.exit(1)) unchanged so the message matches the real file and
invocation.

Comment on lines +1 to +14
import { eq } from 'drizzle-orm';
import { readFileSync } from 'fs';
import { join } from 'path';
import { db } from './index';
import { categories } from './schema/categories';
import {
quizzes,
quizTranslations,
quizQuestions,
quizQuestionContent,
quizAnswers,
quizAnswerTranslations,
quizAttempts,
} from './schema/quiz';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Import paths will fail - script appears misplaced.

This file is located at json/quizzes/angular/advanced/ but imports from ./index and ./schema/*, which would resolve to paths within the json/ directory where no such modules exist. The db instance and schema definitions are in frontend/db/.

Either:

  1. Move this file to frontend/db/seed-quiz-angular-advanced.ts (matching other seed scripts), or
  2. Update imports to use correct relative paths from this location.
Suggested fix if moving to frontend/db/
-import { db } from './index';
-import { categories } from './schema/categories';
+import { db } from './index';
+import { categories } from './schema/categories';

No changes needed if moved to frontend/db/ since the imports would then resolve correctly.

🤖 Prompt for AI Agents
In @json/quizzes/angular/advanced/seed-quiz-angular-advanced.ts around lines 1 -
14, The seed file's imports (db, categories, quizzes, quizTranslations,
quizQuestions, quizQuestionContent, quizAnswers, quizAnswerTranslations,
quizAttempts) are resolving incorrectly because the file is in
json/quizzes/angular/advanced; either move the file into the same directory as
the DB code (so existing imports work) or change the import statements to import
the db instance and schema symbols from the real frontend DB module locations;
update the import sources for "db" and the "./schema/*" modules to point at the
modules that actually export those symbols so the named imports (db, categories,
quizzes, quizTranslations, quizQuestions, quizQuestionContent, quizAnswers,
quizAnswerTranslations, quizAttempts) resolve correctly.

Comment on lines +64 to +68
async function loadQuestions(partNumber: number): Promise<QuestionData[]> {
const partPath = join(process.cwd(), 'data', `angular-advanced-quiz-part${partNumber}.json`);
const partData: QuizPartData = JSON.parse(readFileSync(partPath, 'utf-8'));
return partData.questions;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Incorrect JSON file path.

The path uses 'data' folder, but based on the AI summary and other seed scripts, the JSON files are located at json/quizzes/angular/advanced/angular-advanced-quiz-part{N}.json.

Suggested fix
+const projectRoot = existsSync(join(process.cwd(), 'json'))
+  ? process.cwd()
+  : join(process.cwd(), '..');
+
 async function loadQuestions(partNumber: number): Promise<QuestionData[]> {
-  const partPath = join(process.cwd(), 'data', `angular-advanced-quiz-part${partNumber}.json`);
+  const partPath = join(projectRoot, 'json', 'quizzes', 'angular', 'advanced', `angular-advanced-quiz-part${partNumber}.json`);
   const partData: QuizPartData = JSON.parse(readFileSync(partPath, 'utf-8'));
   return partData.questions;
 }
🤖 Prompt for AI Agents
In @json/quizzes/angular/advanced/seed-quiz-angular-advanced.ts around lines 64
- 68, The loadQuestions function uses the wrong base folder; update the path
creation in loadQuestions to point to the actual JSON location by joining
process.cwd() with 'json', 'quizzes', 'angular', 'advanced' and the file name
`angular-advanced-quiz-part${partNumber}.json` so loadQuestions reads from the
correct JSON files.

Comment on lines +1 to +14
import { eq } from 'drizzle-orm';
import { readFileSync } from 'fs';
import { join } from 'path';
import { db } from './index';
import { categories } from './schema/categories';
import {
quizzes,
quizTranslations,
quizQuestions,
quizQuestionContent,
quizAnswers,
quizAnswerTranslations,
quizAttempts,
} from './schema/quiz';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Find the seed-quiz-nodejs-fundamentals.ts file
fd -t f "seed-quiz-nodejs-fundamentals.ts"

Repository: DevLoversTeam/devlovers.net

Length of output: 137


🏁 Script executed:

# Explore the db directory structure
fd -t f -p "db/" "\.ts$" | head -20

Repository: DevLoversTeam/devlovers.net

Length of output: 163


🏁 Script executed:

# Check for similar seed scripts mentioned in the review
fd -t f "seed-quiz.*\.ts"

Repository: DevLoversTeam/devlovers.net

Length of output: 1093


🏁 Script executed:

# Verify the data directory structure
fd -t d "data" | head -10

Repository: DevLoversTeam/devlovers.net

Length of output: 85


🏁 Script executed:

# Check the json/quizzes directory structure
fd -t f -p "json/quizzes/" | head -30

Repository: DevLoversTeam/devlovers.net

Length of output: 1683


🏁 Script executed:

# Check what files exist in the node beginner_medium directory
fd -t f -p "json/quizzes/node/beginner_medium/"

Repository: DevLoversTeam/devlovers.net

Length of output: 365


🏁 Script executed:

# Look at the actual content of the file to see the full import statements and data loading logic
cat -n "json/quizzes/node/beginner_medium/seed-quiz-nodejs-fundamentals.ts" | head -50

Repository: DevLoversTeam/devlovers.net

Length of output: 1588


🏁 Script executed:

# Compare with another seed script from json/quizzes to see if they have the same import pattern
cat -n "json/quizzes/angular/beginner_medium/seed-quiz-angular.ts" | head -50

Repository: DevLoversTeam/devlovers.net

Length of output: 1596


🏁 Script executed:

# Check if there's a frontend/db structure and verify the index location
ls -la frontend/db/ 2>/dev/null | head -20

Repository: DevLoversTeam/devlovers.net

Length of output: 1405


🏁 Script executed:

# Check if index.ts and schema directories exist in the json/quizzes directories
fd -t f "index.ts" -p "json/quizzes/"

Repository: DevLoversTeam/devlovers.net

Length of output: 53


🏁 Script executed:

# Check for schema directories in json/quizzes
fd -t d "schema" -p "json/quizzes/"

Repository: DevLoversTeam/devlovers.net

Length of output: 53


🏁 Script executed:

# Look at the complete file to see how data is loaded
cat -n "json/quizzes/node/beginner_medium/seed-quiz-nodejs-fundamentals.ts" | head -100

Repository: DevLoversTeam/devlovers.net

Length of output: 3718


🏁 Script executed:

# Compare with the frontend/db/seed-quiz-nodejs-advanced.ts to see if imports differ
head -20 "frontend/db/seed-quiz-nodejs-advanced.ts"

Repository: DevLoversTeam/devlovers.net

Length of output: 541


Imports are broken and will fail at runtime. File imports from non-existent relative paths.

The imports reference './index' and './schema/categories' which don't exist in json/quizzes/node/beginner_medium/. These modules are located in frontend/db/, not relative to this seed script's directory. The file cannot execute with these imports.

Additionally, the data loading path at line 65 uses join(process.cwd(), 'data', ...) but the actual quiz data files are in the same directory as the script (nodejs-quiz-part1.json, etc.), making readFileSync fail at runtime.

🤖 Prompt for AI Agents
In @json/quizzes/node/beginner_medium/seed-quiz-nodejs-fundamentals.ts around
lines 1 - 14, The imports at the top (db, categories, quizzes, quizTranslations,
quizQuestions, quizQuestionContent, quizAnswers, quizAnswerTranslations,
quizAttempts) are pointing to non-existent relative paths (e.g., './index' and
'./schema/categories'); update those import specifiers to the correct module
locations under the actual frontend/db package (replace './index' and
'./schema/...' with the appropriate 'frontend/db/...' module paths used by the
project) so symbols like db and categories resolve at runtime, and change the
data file loading (currently using join(process.cwd(), 'data', ...)) to load
from the seed file's directory (use the script's directory as the base, e.g.,
using __dirname or path.join(dirname, 'nodejs-quiz-part1.json')) so readFileSync
reads the local JSON files like nodejs-quiz-part1.json successfully.

Comment on lines +64 to +68
async function loadQuestions(partNumber: number): Promise<QuestionData[]> {
const partPath = join(process.cwd(), 'data', `nodejs-quiz-part${partNumber}.json`);
const partData: QuizPartData = JSON.parse(readFileSync(partPath, 'utf-8'));
return partData.questions;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Inconsistent data path and missing file existence check.

This script uses join(process.cwd(), 'data', ...) while the other seed scripts in this PR (e.g., seed-quiz-nodejs-advanced.ts, seed-quiz-vue.ts) use a projectRoot detection pattern with existsSync. Additionally, the path structure differs—other scripts reference json/quizzes/<category>/... paths.

Consider aligning with the pattern used in sibling scripts for consistency:

♻️ Suggested alignment
+const projectRoot = existsSync(join(process.cwd(), 'json'))
+  ? process.cwd()
+  : join(process.cwd(), '..');
+
 async function loadQuestions(partNumber: number): Promise<QuestionData[]> {
-  const partPath = join(process.cwd(), 'data', `nodejs-quiz-part${partNumber}.json`);
+  const partPath = join(projectRoot, 'json', 'quizzes', 'node', 'beginner_medium', `nodejs-quiz-part${partNumber}.json`);
   const partData: QuizPartData = JSON.parse(readFileSync(partPath, 'utf-8'));
   return partData.questions;
 }
📝 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
async function loadQuestions(partNumber: number): Promise<QuestionData[]> {
const partPath = join(process.cwd(), 'data', `nodejs-quiz-part${partNumber}.json`);
const partData: QuizPartData = JSON.parse(readFileSync(partPath, 'utf-8'));
return partData.questions;
}
const projectRoot = existsSync(join(process.cwd(), 'json'))
? process.cwd()
: join(process.cwd(), '..');
async function loadQuestions(partNumber: number): Promise<QuestionData[]> {
const partPath = join(projectRoot, 'json', 'quizzes', 'node', 'beginner_medium', `nodejs-quiz-part${partNumber}.json`);
const partData: QuizPartData = JSON.parse(readFileSync(partPath, 'utf-8'));
return partData.questions;
}
🤖 Prompt for AI Agents
In @json/quizzes/node/beginner_medium/seed-quiz-nodejs-fundamentals.ts around
lines 64 - 68, The loadQuestions function uses process.cwd() and lacks a file
existence check; change it to use the same projectRoot detection pattern as
sibling seed scripts (compute projectRoot, then build the path under
json/quizzes/node/beginner_medium or the canonical directory used by other
scripts) and call existsSync to verify the file exists before readFileSync; if
the file is missing, throw or log a clear error. Update references inside
loadQuestions (function name) and local variables (partPath, partData)
accordingly so the path resolution and existence check match the other seed
scripts.

Comment on lines +4 to +14
import { db } from './index';
import { categories } from './schema/categories';
import {
quizzes,
quizTranslations,
quizQuestions,
quizQuestionContent,
quizAnswers,
quizAnswerTranslations,
quizAttempts,
} from './schema/quiz';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Verify import paths resolve correctly from this file location.

This file is located at json/quizzes/vue/beginner_medium/seed-quiz-vue.ts, but the imports reference './index' and './schema/...'. Based on the codebase structure, the db module is at frontend/db/index.ts. These relative paths will not resolve correctly from the current file location.

Suggested fix

Either:

  1. Move this script to frontend/db/seeds/ directory to match the usage message, or
  2. Update imports to use the correct relative path to frontend/db/:
-import { db } from './index';
-import { categories } from './schema/categories';
+import { db } from '../../../../frontend/db/index';
+import { categories } from '../../../../frontend/db/schema/categories';
 import {
   quizzes,
   quizTranslations,
   quizQuestions,
   quizQuestionContent,
   quizAnswers,
   quizAnswerTranslations,
   quizAttempts,
-} from './schema/quiz';
+} from '../../../../frontend/db/schema/quiz';
📝 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
import { db } from './index';
import { categories } from './schema/categories';
import {
quizzes,
quizTranslations,
quizQuestions,
quizQuestionContent,
quizAnswers,
quizAnswerTranslations,
quizAttempts,
} from './schema/quiz';
import { db } from '../../../../frontend/db/index';
import { categories } from '../../../../frontend/db/schema/categories';
import {
quizzes,
quizTranslations,
quizQuestions,
quizQuestionContent,
quizAnswers,
quizAnswerTranslations,
quizAttempts,
} from '../../../../frontend/db/schema/quiz';

Comment on lines +64 to +68
async function loadQuestions(partNumber: number): Promise<QuestionData[]> {
const partPath = join(process.cwd(), 'data', `vue-quiz-part${partNumber}.json`);
const partData: QuizPartData = JSON.parse(readFileSync(partPath, 'utf-8'));
return partData.questions;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Incorrect JSON file path will cause runtime failure.

The path join(process.cwd(), 'data', ...) looks for files in a data/ directory relative to the working directory. According to the PR context, the JSON files (vue-quiz-part1.json through vue-quiz-part4.json) are located in json/quizzes/vue/beginner_medium/ alongside this script.

Suggested fix
 async function loadQuestions(partNumber: number): Promise<QuestionData[]> {
-  const partPath = join(process.cwd(), 'data', `vue-quiz-part${partNumber}.json`);
+  const partPath = join(__dirname, `vue-quiz-part${partNumber}.json`);
   const partData: QuizPartData = JSON.parse(readFileSync(partPath, 'utf-8'));
   return partData.questions;
 }

Note: If using ES modules, you may need to derive __dirname using:

import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
🤖 Prompt for AI Agents
In @json/quizzes/vue/beginner_medium/seed-quiz-vue.ts around lines 64 - 68, The
loadQuestions function currently builds partPath using process.cwd() which can
point to the wrong working directory; change it to resolve the JSON files
relative to this script by using __dirname (i.e. compute partPath with
path.join(__dirname, `vue-quiz-part${partNumber}.json`) or join(__dirname,
'json/quizzes/vue/beginner_medium', ... ) depending on where the files live) so
loadQuestions reads the files next to the script; if this repo uses ES modules,
derive __dirname via fileURLToPath(import.meta.url) and dirname before using it.

Comment on lines +186 to +189
console.error('Error: Please specify which part to upload');
console.log('Usage: npx tsx db/seeds/seed-quiz-vue.ts <part-number>');
console.log('Example: npx tsx db/seeds/seed-quiz-vue.ts 1');
console.log('Or upload all: npx tsx db/seeds/seed-quiz-vue.ts all');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Update usage message to reflect actual file path.

The usage examples reference db/seeds/seed-quiz-vue.ts, but this file is located at json/quizzes/vue/beginner_medium/seed-quiz-vue.ts.

Suggested fix
     console.error('Error: Please specify which part to upload');
-    console.log('Usage: npx tsx db/seeds/seed-quiz-vue.ts <part-number>');
-    console.log('Example: npx tsx db/seeds/seed-quiz-vue.ts 1');
-    console.log('Or upload all: npx tsx db/seeds/seed-quiz-vue.ts all');
+    console.log('Usage: npx tsx json/quizzes/vue/beginner_medium/seed-quiz-vue.ts <part-number>');
+    console.log('Example: npx tsx json/quizzes/vue/beginner_medium/seed-quiz-vue.ts 1');
+    console.log('Or upload all: npx tsx json/quizzes/vue/beginner_medium/seed-quiz-vue.ts all');
📝 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
console.error('Error: Please specify which part to upload');
console.log('Usage: npx tsx db/seeds/seed-quiz-vue.ts <part-number>');
console.log('Example: npx tsx db/seeds/seed-quiz-vue.ts 1');
console.log('Or upload all: npx tsx db/seeds/seed-quiz-vue.ts all');
console.error('Error: Please specify which part to upload');
console.log('Usage: npx tsx json/quizzes/vue/beginner_medium/seed-quiz-vue.ts <part-number>');
console.log('Example: npx tsx json/quizzes/vue/beginner_medium/seed-quiz-vue.ts 1');
console.log('Or upload all: npx tsx json/quizzes/vue/beginner_medium/seed-quiz-vue.ts all');
🤖 Prompt for AI Agents
In @json/quizzes/vue/beginner_medium/seed-quiz-vue.ts around lines 186 - 189,
Update the usage/help messages currently printed by the script (the
console.error and console.log calls) to reference the actual path and invocation
for this file (json/quizzes/vue/beginner_medium/seed-quiz-vue.ts) instead of
db/seeds/seed-quiz-vue.ts; locate the console.error('Error: Please specify which
part to upload') and the following console.log(...) lines and change their
strings to show the correct path and examples (e.g., npx tsx
json/quizzes/vue/beginner_medium/seed-quiz-vue.ts <part-number> and
corresponding example for "all").

@ViktorSvertoka ViktorSvertoka merged commit 7d152a3 into develop Jan 13, 2026
9 checks passed
@ViktorSvertoka ViktorSvertoka deleted the sl/feat/quiz branch January 13, 2026 21:58
@LesiaUKR LesiaUKR restored the sl/feat/quiz branch January 13, 2026 22:20
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.

(SP: 2) [Database] Seed quizzes for Angular, Vue, and Node.js categories (SP: 1) [Frontend] Fix timer restart on language switch during quiz

2 participants