Skip to content

(SP: 5) [Quiz] Redis caching + guest session fix + cleanup#263

Merged
ViktorSvertoka merged 25 commits intodevelopfrom
sl/feat/quiz
Feb 3, 2026
Merged

(SP: 5) [Quiz] Redis caching + guest session fix + cleanup#263
ViktorSvertoka merged 25 commits intodevelopfrom
sl/feat/quiz

Conversation

@LesiaUKR
Copy link
Collaborator

@LesiaUKR LesiaUKR commented Feb 3, 2026

Summary

Closes #260
Closes #261
Closes #262

  • Implement Redis caching for quiz answer verification (replaces AES-256-GCM encryption)
  • Fix guest language switch on result screen
  • Remove redundant files after Redis migration
  • Improve accessibility with WCAG-compliant color contrast

Issues Closed

Issue SP Description
#260 3 Redis cache for quiz answer verification
#261 1 Guest language switch fix
#262 1 Codebase cleanup

Changes

Redis Cache (#260)

  • Cache correct answers per quiz in Redis (12h TTL)
  • Replace AES decryption with O(1) Redis lookup
  • Single DB query per cache miss (shared by all users)
  • Add initializeQuizCache server action

Guest Language Switch Fix (#261)

  • Guest result screen survives language switch
  • Session with completed status is now restored

Codebase Cleanup (#262)

Deleted Reason
PendingResultHandler.tsx Never runs (auth → dashboard)
start-session/route.ts Broken import, unused
quiz-crypto.ts AES replaced by Redis
quiz-crypto.test.ts Tests dead code

WCAG Accessibility

  • Improved color contrast for quiz UI elements
  • Compliant with WCAG 2.1 AA standards

Known Limitations (documented)

  • Server-side time enforcement deferred (low priority)
  • Hydration flash on refresh (~100-300ms)

Test Results

  • All 66 quiz tests pass
  • verify-answer.test.ts rewritten for Redis API

Test plan

  • Authenticated user: quiz flow with points
  • Guest user: quiz flow with "Login to save"
  • Guest → auth sync: pending result saved on dashboard
  • Language switch mid-quiz: progress preserved
  • Language switch on guest result: result preserved

Summary by CodeRabbit

  • New Features

    • Debug endpoints to inspect and clear quiz answer cache in development.
  • Improvements

    • Accessibility enhancements (aria-hidden for decorative icons).
    • Quiz start now initializes server-side cache to reduce verification latency.
    • Dashboard and layout utility refinements.
  • Bug Fixes

    • More reliable session restoration (completed sessions load correctly).
    • Simplified answer verification flow with clearer success/error responses.

…(issues #181, #193, #194)

- Refactor QaTabButton to shared CategoryTabButton component
- Add category accent colors to QuizCard, buttons, progress indicators
- Standardize colors with CSS variables, traffic light timer
- Add DynamicGridBackground to quizzes list page
- Border-only answer feedback, semi-transparent progress styles
Changed violationsCount > 3 to >= 3 in QuizResult points block
to match the warning banner threshold at line 124.
- Configure Vitest for quiz module
- Add test factories and setup utilities
- Add quiz-crypto tests (13 tests)
- Add quiz-session tests (12 tests)
…eat hook (#199)

- verify-answer.test.ts: 8 tests for API endpoint
  - Correct/wrong answer verification
  - Validation errors (missing fields, tampered data)
  - Security: rejects modified encrypted answers

- quiz-anticheat.test.ts: 10 tests for useAntiCheat hook
  - Detects copy, paste, context-menu, tab-switch events
  - Respects isActive flag
  - Reset and cleanup functionality

Total quiz tests: 52 (9 setup + 25 unit + 18 integration)
…UI flow

Add 28 new tests covering:
- useQuizSession hook (6 tests)
- useQuizGuards hook (8 tests)
- guest-quiz storage (5 tests)
- guest-result API route (5 tests)
- quiz-slug API route (3 tests)
- QuizContainer UI flow (1 test)

Coverage: 35% -> 90.94% (quiz scope)
Tests: 52 -> 80
Closes #260, #261, #262

- Add quiz-answers-redis.ts with getOrCreateQuizAnswersCache()
- Cache correct answers per quiz (12h TTL)
- Replace AES-256-GCM decryption with O(1) Redis lookup
- Add initializeQuizCache server action
- Update verify-answer route to use Redis

- Allow restoring 'completed' sessions (not just 'in_progress')
- Only clear session for authenticated users after submit
- Guest result screen now survives language switch

- Delete PendingResultHandler.tsx (never executes)
- Delete start-session/route.ts (broken import, unused)
- Delete quiz-crypto.ts (AES replaced by Redis)
- Delete quiz-crypto.test.ts (tests dead code)
- Rewrite verify-answer.test.ts for Redis API (8 tests)
- Fix quiz-session.test.ts for completed session restore
Part of #262 cleanup - route had broken import after Redis migration.
- Validate seed param to prevent NaN breaking question shuffle
- Add cache recovery in verify-answer when Redis cache expires
- Add DB fallback in getCorrectAnswer when Redis unavailable
@vercel
Copy link
Contributor

vercel bot commented Feb 3, 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 3, 2026 6:10pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 3, 2026

📝 Walkthrough

Walkthrough

Migrates quiz answer verification from client-side encryption to a Redis-backed server cache. Adds cache utilities and initialization action, updates verify-answer API and quiz components to use cached answers, removes crypto module and PendingResultHandler, adds Redis debug routes, and performs widespread import/formatting cleanup.

Changes

Cohort / File(s) Summary
Redis quiz cache & API
frontend/lib/quiz/quiz-answers-redis.ts, frontend/actions/quiz.ts, frontend/app/api/quiz/verify-answer/route.ts
Added Redis-backed quiz answer cache (getOrCreateQuizAnswersCache, getCorrectAnswer); new initializeQuizCache action; verify-answer now queries cache (payload: quizId, questionId, selectedAnswerId) and returns { success, isCorrect }.
Debug endpoints
frontend/app/api/debug/redis/route.ts, frontend/app/api/debug/redis-clear/route.ts
New dev-only GET/DELETE endpoints to inspect and clear quiz:answers:* keys from Redis.
Removed crypto & tests
frontend/lib/quiz/quiz-crypto.ts, frontend/lib/tests/quiz/quiz-crypto.test.ts
Deleted AES-based quiz encryption/decryption module and its test suite.
Quiz components & props
frontend/components/quiz/QuizContainer.tsx, frontend/components/quiz/QuizResult.tsx, frontend/components/quiz/QuizQuestion.tsx, frontend/components/quiz/QuizProgress.tsx, frontend/components/quiz/CountdownTimer.tsx, frontend/components/quiz/QuizCard.tsx
Removed encryptedAnswers prop; initialize cache on start; verify requests updated; replaced AlertTriangleTriangleAlert; accessibility additions (aria-hidden, shrink-0); removed quizSlug from QuizResult; minor UI/class updates.
Pending result flow
frontend/components/quiz/PendingResultHandler.tsx, frontend/components/auth/PostAuthQuizSync.tsx
Deleted PendingResultHandler component; PostAuthQuizSync removed router usage and uses window.location.reload() after successful sync.
Quiz page & session
frontend/app/[locale]/quiz/[slug]/page.tsx, frontend/lib/quiz/quiz-session.ts
Redirect when missing/invalid seed; removed encrypted blob creation and PendingResultHandler render; session restore logic relaxed to allow completed to be loaded.
Verification tests & mocks
frontend/lib/tests/quiz/verify-answer.test.ts, frontend/lib/tests/quiz/quiz-session.test.ts
Updated verify-answer tests to mock Redis/getCorrectAnswer and new request shape; removed crypto tests; adjusted quiz-session expectations for completed sessions.
Seed & db scripts
frontend/db/seed-quiz-react.ts, other seed files
Renamed cleanupReactQuiz to _cleanupReactQuiz and removed its invocation; small import spacing fixes.
Formatting & imports
50+ files (components, tests, db queries, services, utils) e.g., frontend/app/[locale]/dashboard/page.tsx, frontend/components/**, frontend/db/..., frontend/lib/...
Widespread import spacing and formatting changes, minor Tailwind utility renames/sizing updates, and removal of unused imports (cosmetic).
Config updates
frontend/eslint.config.mjs, frontend/tsconfig.json
Added _dev-notes/** to ESLint globalIgnores; added "node" to TypeScript types.

Sequence Diagram

sequenceDiagram
    participant Client as Quiz Client
    participant Server as API Server
    participant Redis as Redis Cache
    participant DB as Database

    rect rgba(100,150,200,0.5)
    Note over Client,DB: Old Flow (Encryption-Based)
    Client->>Client: Encrypt correct answers (client-side)
    Client->>Server: POST /verify-answer with encryptedAnswers
    Server->>Server: Decrypt encryptedAnswers
    Server->>Server: Compare decrypted answer with submission
    Server->>Client: Return isCorrect
    end

    rect rgba(150,200,100,0.5)
    Note over Client,DB: New Flow (Redis-Cached)
    Client->>Server: POST /quiz/[slug] (start)
    Server->>Server: initializeQuizCache(quizId)
    Server->>DB: Query correct answers for quizId
    Server->>Redis: Cache answers (TTL: 12h)
    Server->>Client: Quiz initialized

    Client->>Server: POST /verify-answer { quizId, questionId, selectedAnswerId }
    Server->>Redis: getCorrectAnswer(quizId, questionId)
    Redis->>Server: Return correctAnswerId
    Server->>Server: Compare selectedAnswerId === correctAnswerId
    Server->>Client: Return { success, isCorrect }
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related issues

Possibly related PRs

Suggested labels

refactor

Suggested reviewers

  • AM1007
  • ViktorSvertoka

Poem

🐰
I cached the answers in a stash so neat,
Redis hums and keeps them quick and sweet.
No more secrets wrapped in crypto's art,
The quiz runs smooth — a rabbit's work of heart.
Hop on, test it — watch the refactor beat!

🚥 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 clearly summarizes the main changes: Redis caching for quiz verification, a guest session fix, and cleanup work. It accurately reflects the primary objectives outlined in the PR.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 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.

@LesiaUKR LesiaUKR changed the base branch from main to develop February 3, 2026 17:14
@netlify
Copy link

netlify bot commented Feb 3, 2026

Deploy Preview for develop-devlovers ready!

Name Link
🔨 Latest commit bf21695
🔍 Latest deploy log https://app.netlify.com/projects/develop-devlovers/deploys/698239e0b3d8ab000861fcb0
😎 Deploy Preview https://deploy-preview-263--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.

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.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@frontend/app/`[locale]/quiz/[slug]/page.tsx:
- Around line 30-36: The code currently uses parseInt(seedParam, 10) without
validating the result, which can yield NaN and break
getQuizQuestionsRandomized/randomizeQuizQuestions; update the logic around
seedParam/parseInt to detect non-numeric or NaN seeds and handle them the same
way as a missing seed (i.e., perform the redirect to
`/${locale}/quiz/${slug}?seed=${Date.now()}`) so only a valid numeric seed is
passed into the seed variable and into getQuizQuestionsRandomized; ensure any
check covers empty string, non-digits, and NaN after parseInt.

In `@frontend/app/api/quiz/verify-answer/route.ts`:
- Around line 3-28: The handler POST currently returns 404 when
getCorrectAnswer(quizId, questionId) yields null even if the cache was evicted;
import and call getOrCreateQuizAnswersCache(quizId) as a fallback to rehydrate
the cache, then retry getCorrectAnswer(quizId, questionId) before returning the
404 via NextResponse; update imports to include getOrCreateQuizAnswersCache and
ensure behavior remains identical if the retry still returns null.

In `@frontend/lib/quiz/quiz-answers-redis.ts`:
- Around line 22-84: getCorrectAnswer returns null on cache miss (or when Redis
is disabled) causing the verify-answer route to 404 even though
getOrCreateQuizAnswersCache allowed the quiz to start; add a DB fallback or
cache rehydration so answer verification works. Update getCorrectAnswer (or the
verify-answer handler) to, on cache miss, either call
getOrCreateQuizAnswersCache(quizId) and re-read redis, or run the same DB query
used in getOrCreateQuizAnswersCache
(db.select(...).from(quizAnswers).innerJoin(quizQuestions,
eq(quizAnswers.quizQuestionId,
quizQuestions.id)).where(and(eq(quizQuestions.quizId, quizId),
eq(quizAnswers.isCorrect, true)))) to find the correct answer for questionId,
populate the answers map and (optionally) set the redis key via
getRedisClient()/getCacheKey with QUIZ_CACHE_TTL_SECONDS; return the found
answerId or null if none. Ensure to reference getOrCreateQuizAnswersCache,
getCorrectAnswer, quizAnswers, quizQuestions, getRedisClient, getCacheKey, and
QUIZ_CACHE_TTL_SECONDS when making the change.
🧹 Nitpick comments (3)
frontend/components/quiz/QuizResult.tsx (1)

15-27: Unused prop quizSlug in interface.

The quizSlug prop is declared in QuizResultProps (line 22) but is no longer destructured or used in the component. This appears to be leftover from the redirect URL change.

🧹 Remove unused prop from interface
 interface QuizResultProps {
   score: number;
   total: number;
   percentage: number;
   answeredCount: number;
   violationsCount?: number;
   isGuest?: boolean;
-  quizSlug?: string;
   pointsAwarded?: number | null;
   isIncomplete?: boolean;
   onRestart: () => void;
   onBackToTopics: () => void;
 }
frontend/components/quiz/QuizQuestion.tsx (1)

58-67: Redundant border class in conditional styling.

Line 59 already includes border in the base class. Lines 64-65 add border border-green-500 and border border-red-500, resulting in duplicate border declarations.

🧹 Remove redundant border class
                 isSelected &&
                   isAnswering &&
                   'border-blue-500 bg-blue-50 dark:bg-blue-950',
-                showCorrect && 'border border-green-500',
-                showIncorrect && 'border border-red-500',
+                showCorrect && 'border-green-500',
+                showIncorrect && 'border-red-500',
                 !isAnswering && 'cursor-default'
frontend/lib/quiz/quiz-session.ts (1)

48-52: Comment is now outdated.

The comment "Only restore in_progress sessions" no longer accurately describes the behavior. The condition now allows both in_progress and completed sessions to be restored (only rules status is cleared).

📝 Update comment to reflect actual behavior
-    // Only restore in_progress sessions
+    // Discard sessions that haven't started yet
     if (data.status === 'rules') {
       clearQuizSession(quizId);
       return null;
     }

@ViktorSvertoka ViktorSvertoka merged commit 1ad1d7f into develop Feb 3, 2026
9 of 10 checks passed
@ViktorSvertoka ViktorSvertoka deleted the sl/feat/quiz branch February 3, 2026 18:14
@LesiaUKR LesiaUKR restored the sl/feat/quiz branch February 3, 2026 21:53
ViktorSvertoka added a commit that referenced this pull request Feb 3, 2026
* chore: bump Node.js to 20 for Netlify

* feat(md) add netlify status (#234)

* (SP 2) [Shop UI] Unify storefront styles across components and interactions (#236)

* Host (#237)

* feat(md) add netlify status

* feat(files): add packages

* fix(auth): use currentTarget for email input validity

* Host (#238)

* feat(md) add netlify status

* feat(files): add packages

* fix(auth): use currentTarget for email input validity

* fix(auth): use currentTarget for email input validity

* fix(auth): use currentTarget in password field

* (SP 1) [Shop UI] Add page metadata across shop routes (#239)

* (SP 2) [Shop UI] Unify storefront styles across components and interactions

* (SP 1) [Shop UI] Add page metadata across shop routes

* (SP: 3) [Cache] Add Upstash Redis cache for Q&A (#241)

* feat(md) add netlify status

* feat(files): add packages

* fix(auth): use currentTarget for email input validity

* fix(auth): use currentTarget for email input validity

* fix(auth): use currentTarget in password field

* feat(qa): add Redis cache layer for Q&A

* Fix Q&A Redis cache parsing for Upstash REST (#243)

* feat(md) add netlify status

* feat(files): add packages

* fix(auth): use currentTarget for email input validity

* fix(auth): use currentTarget for email input validity

* fix(auth): use currentTarget in password field

* feat(qa): add Redis cache layer for Q&A

* fix(qa): handle non-string Redis cache values

* feat(Blog):Adding pagination (#244)

* feat(Blog):fix for clickable link in post details, fix for author details

* feat(Blog):refactoring after removing author modal

* feat(Blog): fix unified date format

* feat(Blog): Fix for  click-outside-to-close search, recommended posts are limited to 3

* feat(Blog): selectedAuthorData fixed

* feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders

* feat(Blog): fix hover social links, fixed duplication not found search

* feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs

* feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs

* feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations

* feat(Blog): Changed image size on the post details page

* feat(Blog): added tests

* feat(Blog): fix for big post on the post page, added tests

* feat(Blog): resolving comments

* feat(Blog): fixed hover for social links icins - dark theme

* feat(Blog): bringing the style on the blog page to a single site style

* feat(blog): aligning syles

* feat(blog): resolving comment from CodeRabbit

* feat(blog):fix comment for deployment

* feat(Blog): adding pagination

* feat(Blog): Addind Text formatting visibility

* (SP:2) feat(api): clean up AI helper for Vercel & fix orders i18n (#245)

- Refactor /api/ai/explain route for Vercel deployment
    - Replace dynamic import with static import of groq-sdk
    - Use request.json() instead of Netlify-safe body parsing
    - Add proper error handling with Groq.APIError types
    - Simplify GET health check endpoint
    - Update model from llama3-70b-8192 to llama-3.3-70b-versatile
- Add table.openOrder and table.orderId to en/uk/pl locales

* refactor(home): update button, cards, and online counter UI (#248)

Improve primary button styles
Fix card overflow and add subtle highlights
Redesign online users counter and reduce font size

* fix(api): enforce rate limiting (#246)

* (SP:2) feat(api): clean up AI helper for Vercel & fix orders i18n

  - Refactor /api/ai/explain route for Vercel deployment
    - Replace dynamic import with static import of groq-sdk
    - Use request.json() instead of Netlify-safe body parsing
    - Add proper error handling with Groq.APIError types
    - Simplify GET health check endpoint
    - Update model from llama3-70b-8192 to llama-3.3-70b-versatile
- Add table.openOrder and table.orderId to en/uk/pl locales

* fix(api): enforce rate limiting

---------

Co-authored-by: Viktor Svertoka <victor.svertoka@gmail.com>

* feat(Blog):formating text (#249)

* feat(Blog):fix for clickable link in post details, fix for author details

* feat(Blog):refactoring after removing author modal

* feat(Blog): fix unified date format

* feat(Blog): Fix for  click-outside-to-close search, recommended posts are limited to 3

* feat(Blog): selectedAuthorData fixed

* feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders

* feat(Blog): fix hover social links, fixed duplication not found search

* feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs

* feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs

* feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations

* feat(Blog): Changed image size on the post details page

* feat(Blog): added tests

* feat(Blog): fix for big post on the post page, added tests

* feat(Blog): resolving comments

* feat(Blog): fixed hover for social links icins - dark theme

* feat(Blog): bringing the style on the blog page to a single site style

* feat(blog): aligning syles

* feat(blog): resolving comment from CodeRabbit

* feat(blog):fix comment for deployment

* feat(Blog): adding pagination

* feat(Blog): Addind Text formatting visibility

* feat(Blog):adding text formating fix

* ref(files): refactoring code & bag fix (#250)

* chore(release): v0.5.2

* Lso/feat/shop design (#252)

* feat(i18n): add translations for blog categories, and UI components (#253)

- Translate blog category labels in mobile menu, cards, and filters
  - Add CTA hover variants translations
  - Add aria-label translations for theme toggle, cart, search, GitHub star
  - Update translation files for EN, UK, PL locales

* feat blog: fix for paddings on mobile  (#254)

* feat(Blog):fix for clickable link in post details, fix for author details

* feat(Blog):refactoring after removing author modal

* feat(Blog): fix unified date format

* feat(Blog): Fix for  click-outside-to-close search, recommended posts are limited to 3

* feat(Blog): selectedAuthorData fixed

* feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders

* feat(Blog): fix hover social links, fixed duplication not found search

* feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs

* feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs

* feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations

* feat(Blog): Changed image size on the post details page

* feat(Blog): added tests

* feat(Blog): fix for big post on the post page, added tests

* feat(Blog): resolving comments

* feat(Blog): fixed hover for social links icins - dark theme

* feat(Blog): bringing the style on the blog page to a single site style

* feat(blog): aligning syles

* feat(blog): resolving comment from CodeRabbit

* feat(blog):fix comment for deployment

* feat(Blog): adding pagination

* feat(Blog): Addind Text formatting visibility

* feat(Blog):adding text formating fix

* chore(lint): finalize ESLint + Prettier (#256)

* feat(leaderboard): finalize components and fix lint errors (#259)

* (SP 1) [FIX] set up eslint/prettier + stabilize formatting workflow (own files only) (#264)

* (SP 2) [Shop UI] Unify storefront styles across components and interactions

* (SP 1) [Shop UI] Add page metadata across shop routes

* (SP 1) [FIX] names of components, replacing tests, clean code

* (SP 1) [FIX] remove magic constant and align restock sweep test typing

* (SP 1) [FIX] remove duplicate

* (SP 1) [FIX] set up eslint/prettier + stabilize formatting workflow (own files only)

* (SP 1) [FIX] Tailwind hints

* (SP 1) [FIX] Tailwind hints revert

* (SP: 5) [Quiz] Redis caching + guest session fix + cleanup (#263)

* feat(quiz-ui): quiz UI polish - tabs, category accents, color scheme (issues #181, #193, #194)

- Refactor QaTabButton to shared CategoryTabButton component
- Add category accent colors to QuizCard, buttons, progress indicators
- Standardize colors with CSS variables, traffic light timer
- Add DynamicGridBackground to quizzes list page
- Border-only answer feedback, semi-transparent progress styles

* docs: update .gitignore

* fix(quiz): align disqualification threshold with warning banner

Changed violationsCount > 3 to >= 3 in QuizResult points block
to match the warning banner threshold at line 124.

* feat(quiz-testing): add quiz unit tests

- Configure Vitest for quiz module
- Add test factories and setup utilities
- Add quiz-crypto tests (13 tests)
- Add quiz-session tests (12 tests)

* test(quiz): add integration tests for verify-answer API and useAntiCheat hook (#199)

- verify-answer.test.ts: 8 tests for API endpoint
  - Correct/wrong answer verification
  - Validation errors (missing fields, tampered data)
  - Security: rejects modified encrypted answers

- quiz-anticheat.test.ts: 10 tests for useAntiCheat hook
  - Detects copy, paste, context-menu, tab-switch events
  - Respects isActive flag
  - Reset and cleanup functionality

Total quiz tests: 52 (9 setup + 25 unit + 18 integration)

* test(quiz): expand test coverage to 90%+ with hooks, API routes, and UI flow

Add 28 new tests covering:
- useQuizSession hook (6 tests)
- useQuizGuards hook (8 tests)
- guest-quiz storage (5 tests)
- guest-result API route (5 tests)
- quiz-slug API route (3 tests)
- QuizContainer UI flow (1 test)

Coverage: 35% -> 90.94% (quiz scope)
Tests: 52 -> 80

* chore: remove coverage-quiz from git, add to .gitignore

* chore: add coverage-quiz to .gitignore, fix quiz guards test

* fix(a11y): improve quiz accessibility and i18n compliance

* fix(sl/feat/quiz): replace with correct name for react icon

* feat(quiz): implement Redis caching + session fixes + cleanup

Closes #260, #261, #262

- Add quiz-answers-redis.ts with getOrCreateQuizAnswersCache()
- Cache correct answers per quiz (12h TTL)
- Replace AES-256-GCM decryption with O(1) Redis lookup
- Add initializeQuizCache server action
- Update verify-answer route to use Redis

- Allow restoring 'completed' sessions (not just 'in_progress')
- Only clear session for authenticated users after submit
- Guest result screen now survives language switch

- Delete PendingResultHandler.tsx (never executes)
- Delete start-session/route.ts (broken import, unused)
- Delete quiz-crypto.ts (AES replaced by Redis)
- Delete quiz-crypto.test.ts (tests dead code)
- Rewrite verify-answer.test.ts for Redis API (8 tests)
- Fix quiz-session.test.ts for completed session restore

* chore(quiz): delete unused start-session route

Part of #262 cleanup - route had broken import after Redis migration.

* git commit -m "fix(quiz): add NaN seed validation and cache/DB fallback

- Validate seed param to prevent NaN breaking question shuffle
- Add cache recovery in verify-answer when Redis cache expires
- Add DB fallback in getCorrectAnswer when Redis unavailable

* chore: remove redis ttl for static quiz and qa caches (#265)

* fix(layout): remove duplicate padding from quiz routes (#266)

* feat(quiz-ui): quiz UI polish - tabs, category accents, color scheme (issues #181, #193, #194)

- Refactor QaTabButton to shared CategoryTabButton component
- Add category accent colors to QuizCard, buttons, progress indicators
- Standardize colors with CSS variables, traffic light timer
- Add DynamicGridBackground to quizzes list page
- Border-only answer feedback, semi-transparent progress styles

* docs: update .gitignore

* fix(quiz): align disqualification threshold with warning banner

Changed violationsCount > 3 to >= 3 in QuizResult points block
to match the warning banner threshold at line 124.

* feat(quiz-testing): add quiz unit tests

- Configure Vitest for quiz module
- Add test factories and setup utilities
- Add quiz-crypto tests (13 tests)
- Add quiz-session tests (12 tests)

* test(quiz): add integration tests for verify-answer API and useAntiCheat hook (#199)

- verify-answer.test.ts: 8 tests for API endpoint
  - Correct/wrong answer verification
  - Validation errors (missing fields, tampered data)
  - Security: rejects modified encrypted answers

- quiz-anticheat.test.ts: 10 tests for useAntiCheat hook
  - Detects copy, paste, context-menu, tab-switch events
  - Respects isActive flag
  - Reset and cleanup functionality

Total quiz tests: 52 (9 setup + 25 unit + 18 integration)

* test(quiz): expand test coverage to 90%+ with hooks, API routes, and UI flow

Add 28 new tests covering:
- useQuizSession hook (6 tests)
- useQuizGuards hook (8 tests)
- guest-quiz storage (5 tests)
- guest-result API route (5 tests)
- quiz-slug API route (3 tests)
- QuizContainer UI flow (1 test)

Coverage: 35% -> 90.94% (quiz scope)
Tests: 52 -> 80

* chore: remove coverage-quiz from git, add to .gitignore

* chore: add coverage-quiz to .gitignore, fix quiz guards test

* fix(a11y): improve quiz accessibility and i18n compliance

* fix(sl/feat/quiz): replace with correct name for react icon

* feat(quiz): implement Redis caching + session fixes + cleanup

Closes #260, #261, #262

- Add quiz-answers-redis.ts with getOrCreateQuizAnswersCache()
- Cache correct answers per quiz (12h TTL)
- Replace AES-256-GCM decryption with O(1) Redis lookup
- Add initializeQuizCache server action
- Update verify-answer route to use Redis

- Allow restoring 'completed' sessions (not just 'in_progress')
- Only clear session for authenticated users after submit
- Guest result screen now survives language switch

- Delete PendingResultHandler.tsx (never executes)
- Delete start-session/route.ts (broken import, unused)
- Delete quiz-crypto.ts (AES replaced by Redis)
- Delete quiz-crypto.test.ts (tests dead code)
- Rewrite verify-answer.test.ts for Redis API (8 tests)
- Fix quiz-session.test.ts for completed session restore

* chore(quiz): delete unused start-session route

Part of #262 cleanup - route had broken import after Redis migration.

* git commit -m "fix(quiz): add NaN seed validation and cache/DB fallback

- Validate seed param to prevent NaN breaking question shuffle
- Add cache recovery in verify-answer when Redis cache expires
- Add DB fallback in getCorrectAnswer when Redis unavailable

* fix(layout): remove duplicate padding from quiz routes

Add isQuizzesPath to MainSwitcher to exclude /quiz and /quizzes routes
from extra px-6 padding, matching Q&A page behavior.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@users.noreply.github.com>
Co-authored-by: KomrakovaAnna <komrakova.anna@gmail.com>
Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com>
Co-authored-by: Yuliia Nazymko <122815071+YNazymko12@users.noreply.github.com>
Co-authored-by: AlinaRyabova <115992255+AlinaRyabova@users.noreply.github.com>
Co-authored-by: Lesia Soloviova <106915140+LesiaUKR@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants