Skip to content

Header UX polish, quiz highlight fix, Blog button styling, shop i18n product descriptions#322

Merged
ViktorSvertoka merged 2 commits intodevelopfrom
feat/translation-leaderboard
Feb 13, 2026
Merged

Header UX polish, quiz highlight fix, Blog button styling, shop i18n product descriptions#322
ViktorSvertoka merged 2 commits intodevelopfrom
feat/translation-leaderboard

Conversation

@TiZorii
Copy link
Collaborator

@TiZorii TiZorii commented Feb 13, 2026

Summary by CodeRabbit

  • New Features

    • Added blog navigation links to mobile and desktop menus.
    • Introduced multi-language product descriptions with improved formatting.
  • Improvements

    • Enhanced product description rendering with support for multiple sources and translations.
    • Updated leaderboard table column widths for consistent layout.
    • Improved quiz route active state detection.
  • Updates

    • Added product descriptions for merchandise items in English, Polish, and Ukrainian.
    • Updated Ukrainian feature section copy.
    • Adjusted navigation ordering and spacing throughout header components.

@vercel
Copy link
Contributor

vercel bot commented Feb 13, 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 13, 2026 8:35pm

@netlify
Copy link

netlify bot commented Feb 13, 2026

Deploy Preview for develop-devlovers ready!

Name Link
🔨 Latest commit 684883c
🔍 Latest deploy log https://app.netlify.com/projects/develop-devlovers/deploys/698f8b13128eb3000839e5b0
😎 Deploy Preview https://deploy-preview-322--develop-devlovers.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 13, 2026

📝 Walkthrough

Walkthrough

This PR introduces localized product descriptions to the shop, adds blog navigation across header components, reorganizes locale ordering, and refines leaderboard and header styling. Product descriptions are now fetched via getMessages and rendered as multi-paragraph text. A blog button with BookOpen icon is integrated into mobile and desktop navigation. Locale configuration shifts to English-first ordering, and translation files expand with product description mappings across multiple languages.

Changes

Cohort / File(s) Summary
Product Description Localization
frontend/app/[locale]/shop/products/[slug]/page.tsx
Replaces single-line product description with multi-source fetching via getMessages. Descriptions now derive from localized shop.productDescriptions with fallback to product.description, and render as multi-paragraph blocks split on newline characters.
Header Navigation Blog Integration
frontend/components/header/AppMobileMenu.tsx, frontend/components/header/DesktopNav.tsx, frontend/components/header/DesktopActions.tsx, frontend/components/header/MobileActions.tsx, frontend/components/header/NavLink.tsx
Adds blog button with BookOpen icon across mobile and desktop header variants, reorders navigation elements to exclude /blog from filtered link lists, updates active-state logic for /quizzes routes, and adjusts element ordering in action bars.
Locale Configuration & Routing
frontend/i18n/config.ts, frontend/components/header/MobileMenuContext.tsx
Reorders locales constant from ['uk', 'en', 'pl'] to ['en', 'uk', 'pl'], updating locale precedence. Adjusts router import from next/navigation to local i18n alias and updates locale-stripping regex to match new order.
Header UI Refinements
frontend/components/shared/LanguageSwitcher.tsx
Reorders localeLabels mapping (uk moved after en) and changes dropdown z-index from arbitrary z-[70] to predefined z-70.
Leaderboard Layout Adjustments
frontend/components/leaderboard/LeaderboardClient.tsx, frontend/components/leaderboard/LeaderboardTable.tsx
Reduces container bottom margin from mb-24 to mb-10. Adds colgroup with consistent column widths (15%, auto, 25%) to header and current-user tables.
Translation Data Expansion
frontend/messages/en.json, frontend/messages/uk.json, frontend/messages/pl.json
Introduces productDescriptions object mapping product identifiers to localized description strings across all three supported languages. Ukrainian file also updates feature copy in about.features section.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • AM1007
  • ViktorSvertoka

Poem

🐰 A blog button hops through the header with glee,
While products don each language for all eyes to see,
The leaderboard tables align column by column,
Locales reordered, navigation more summon—
Header and home now dance in harmony! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
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.
Title check ❓ Inconclusive The title mentions multiple distinct changes (header UX, quiz highlight, blog button, product descriptions) but doesn't clearly prioritize the main change, making it feel like a list of features rather than a cohesive summary. Consider focusing the title on the primary objective (e.g., 'Add blog button and i18n product descriptions' or 'Header navigation refactoring with product i18n'). If multiple items are equally important, clarify which is the main focus.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into develop

✏️ 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 feat/translation-leaderboard

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
frontend/components/header/AppMobileMenu.tsx (1)

260-276: Consider adding isActive to the blog and shop buttons for visual consistency.

In the shop variant (Line 186) and blog variant (Line 217), the respective HeaderButton components include isActive={pathname === '...'}. The platform variant omits isActive for both buttons. If a user navigates to /blog or /shop and returns, the button won't reflect the active state. This may be intentional (since they leave the platform context), but worth confirming it's deliberate.

frontend/components/header/NavLink.tsx (1)

17-17: Hardcoded locale list in regex — consider deriving from config.

Both this file and MobileMenuContext.tsx (line 76) hardcode (uk|en|pl) in the locale-stripping regex. If a locale is added or reordered, these must be updated manually. Consider building the regex from the locales array in @/i18n/config.

♻️ Example
+'use client';
+
+import { usePathname } from 'next/navigation';
+import { locales } from '@/i18n/config';
+import { AnimatedNavLink } from '@/components/shared/AnimatedNavLink';
+
+const localePattern = new RegExp(`^\\/(${locales.join('|')})(?=\\/|$)`);
+
 // then in component:
-    const cleanPathname = pathname.replace(/^\/(uk|en|pl)(?=\/|$)/, '') || '/';
+    const cleanPathname = pathname.replace(localePattern, '') || '/';
frontend/app/[locale]/shop/products/[slug]/page.tsx (2)

57-59: Type safety: (messages as any) bypasses type checking.

The as any cast is consistent with other casts in this file but hides potential issues if the message structure changes. Consider using next-intl's typed message access or at least adding a brief comment noting the expected shape.


137-148: Extract IIFE into a variable for readability.

The immediately-invoked function expression in JSX is harder to scan. Extracting the description resolution above the return statement would simplify the template.

♻️ Suggested refactor
+  const description =
+    (productDescriptions[slug] as string) || product.description;
+
   return (
     <div className="mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8">
       ...
-          {(() => {
-            const desc =
-              (productDescriptions[slug] as string) || product.description;
-            if (!desc) return null;
-            return (
-              <div className="text-muted-foreground mt-6 space-y-2">
-                {desc.split('\n').map((line: string, i: number) => (
-                  <p key={i}>{line}</p>
-                ))}
-              </div>
-            );
-          })()}
+          {description && (
+            <div className="text-muted-foreground mt-6 space-y-2">
+              {description.split('\n').map((line: string, i: number) => (
+                <p key={i}>{line}</p>
+              ))}
+            </div>
+          )}

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.

@ViktorSvertoka ViktorSvertoka merged commit 03b3871 into develop Feb 13, 2026
12 checks passed
@ViktorSvertoka ViktorSvertoka deleted the feat/translation-leaderboard branch February 13, 2026 20:46
ViktorSvertoka added a commit that referenced this pull request Feb 14, 2026
* feat(mobile): improve dashboard, leaderboard & AI helper UX for touch devices

  - Add touch drag support for AI helper modal and explained terms reorder
  - Position explain button below selected word on mobile
  - Show delete/restore buttons always visible on mobile (no hover)
  - Add user avatar to dashboard profile card (same as leaderboard)
  - Fix leaderboard page layout
  - Fix Tailwind v4 canonical class warnings

* Added touchcancel listener

* (SP: 2) [Frontend] Quiz results dashboard, review cache fix, UX improvements (#317)

* (SP: 3) [Backend] add internal janitor (jobs 1-4), claim/lease + runbook (G0-G6) (#318)

* (SP: 2) [Frontend] Redesign Home Hero & Add Features Section (#319)

* refactor(home): rename hero sections and add complete i18n support

- Rename LegacyHeroSection → WelcomeHeroSection
- Rename HeroSection → FeaturesHeroSection
- Add welcomeDescription translation key to eliminate duplication
- Translate all hardcoded text (headings, badges, CTAs)
- Improve Ukrainian/Polish translations for better readability
- Remove unused legacy components and images

* feat(about): update LinkedIn follower count to reflect current stat (1.5k+)

* refactor(home): implement i18n for FlipCardQA & fix memory leaks

* fix(home): resolve rotateY conflict & scope keyboard events in FlipCardQA

* fix(home): resolve all issues

* chore(home): cleanup comments, remove dead code & fix trailing spaces

* (SP: 2) [Frontend] Quiz UX improvements: violations counter, breadcrumbs, status badges (#320)

* feat(quiz): add guest warning before start and bot protection

Guest warning: show login/signup/continue buttons for unauthenticated
users on quiz rules screen before starting.

Bot protection: multi-attempt verification via Redis - each question
can only be verified once per user per attempt. Keys use dynamic TTL
matching quiz time limit and are cleared on retake.

Additional fixes:
- Footer flash on quiz navigation (added loading.tsx, eliminated redirect)
- Renamed QaLoader to Loader for reuse across pages
- React compiler purity errors (crypto.getRandomValues in handlers)
- Start button disabled after retake (isStarting not reset)

* refactor(quiz): PR review feedback

- Extract shared resolveRequestIdentifier() helper to eliminate
  duplicated auth/IP resolution logic in route.ts and actions/quiz.ts
- Return null instead of 'unknown' when identifier unresolvable,
  skip verification tracking for unidentifiable users
- Cap Redis TTL with MAX_TTL (3600s) to prevent client-supplied
  timeLimitSeconds from persisting keys indefinitely
- Add locale prefix to returnTo paths in guest warning links
- Replace nested Button inside Link with styled Link to fix
  invalid HTML (interactive element nesting)

* fix(quiz): fall through to IP when auth cookie is expired/invalid

* feat(quiz): add quiz results dashboard and review page

- Add quiz history section to dashboard with last attempt per quiz
- Add review page showing incorrect questions with explanations
- Add collapsible cards with expand/collapse all toggle
- Add "Review Mistakes" button on quiz result screen
- Add category icons to quiz page and review page headers
- Add BookOpen icon to explanation block in QuizQuestion
- Update guest message to mention error review benefit
- Add i18n translations (en/uk/pl) for all new features

* fix(quiz): scroll to next button on answer reveal, scope review cache by userId

* fix(quiz): restore type imports and userId cache key after merge conflict

* fix: restore type imports, sync @swc/helpers, fix indentation after merge

* feat(quiz): add violations counter UI, fix disqualification threshold

- Add ViolationsCounter component with color escalation (green/yellow/red)
- Sticky top bar keeps counter visible on scroll (mobile/tablet)
- Add i18n counter keys for en/uk/pl with ICU plural forms
- Fix threshold bug: violations warning now triggers at 4+ (was 3+)
  to match actual integrity score calculation (100 - violations * 10 < 70)

* fix(quiz): fix points mismatch between leaderboard and dashboard

Dashboard showed raw pointsEarned from last quiz_attempt, while
leaderboard summed improvement deltas from point_transactions.
Additionally, orphaned transactions from re-seeded quizzes inflated
leaderboard totals (12 rows, 83 ghost points cleaned up in DB).

- Dashboard query now joins point_transactions to show actual awarded
  points per quiz instead of raw attempt score
- Leaderboard query filters out orphaned transactions where the
  source attempt no longer exists in quiz_attempts

* OBfix(quiz): fix points mismatch, consistent status badges, mobile UX

Dashboard showed raw pointsEarned from last attempt while leaderboard
summed improvement deltas from point_transactions. Orphaned transactions
from re-seeded quizzes inflated leaderboard totals (cleaned up in DB).

- Dashboard query joins point_transactions for actual awarded points
- Leaderboard query filters orphaned transactions (source_id not in quiz_attempts)
- Quiz cards use 3-level badges (Mastered/Review/Study) matching dashboard
- Mobile quiz results show dash for zero points, added chevron indicator

* fix(quiz): add breadcrumbs to review page, fix recommendation tautology

* Header UX polish, quiz highlight fix, Blog button styling, shop i18n product    descriptions (#322)

* Header UX: reorder languages, swap controls, fix quiz highlight, style Blog button

* shop i18n product descriptions

* (SP: 1) [Frontend] Q&A: Next.js tab states + faster loader start (#324)

* fix(qa): align Next.js tab states and speed up loader startup

* feat(home,qa): improve home snap flow and add configurable Q&A page size

* fix(i18n,qa,seed): address review issues for locale handling and pagination state

* (SP: 1) [Frontend] Align quiz result messages with status badges, fix locale switch on result page (#325)

* feat(quiz): add guest warning before start and bot protection

Guest warning: show login/signup/continue buttons for unauthenticated
users on quiz rules screen before starting.

Bot protection: multi-attempt verification via Redis - each question
can only be verified once per user per attempt. Keys use dynamic TTL
matching quiz time limit and are cleared on retake.

Additional fixes:
- Footer flash on quiz navigation (added loading.tsx, eliminated redirect)
- Renamed QaLoader to Loader for reuse across pages
- React compiler purity errors (crypto.getRandomValues in handlers)
- Start button disabled after retake (isStarting not reset)

* refactor(quiz): PR review feedback

- Extract shared resolveRequestIdentifier() helper to eliminate
  duplicated auth/IP resolution logic in route.ts and actions/quiz.ts
- Return null instead of 'unknown' when identifier unresolvable,
  skip verification tracking for unidentifiable users
- Cap Redis TTL with MAX_TTL (3600s) to prevent client-supplied
  timeLimitSeconds from persisting keys indefinitely
- Add locale prefix to returnTo paths in guest warning links
- Replace nested Button inside Link with styled Link to fix
  invalid HTML (interactive element nesting)

* fix(quiz): fall through to IP when auth cookie is expired/invalid

* feat(quiz): add quiz results dashboard and review page

- Add quiz history section to dashboard with last attempt per quiz
- Add review page showing incorrect questions with explanations
- Add collapsible cards with expand/collapse all toggle
- Add "Review Mistakes" button on quiz result screen
- Add category icons to quiz page and review page headers
- Add BookOpen icon to explanation block in QuizQuestion
- Update guest message to mention error review benefit
- Add i18n translations (en/uk/pl) for all new features

* fix(quiz): scroll to next button on answer reveal, scope review cache by userId

* fix(quiz): restore type imports and userId cache key after merge conflict

* fix: restore type imports, sync @swc/helpers, fix indentation after merge

* feat(quiz): add violations counter UI, fix disqualification threshold

- Add ViolationsCounter component with color escalation (green/yellow/red)
- Sticky top bar keeps counter visible on scroll (mobile/tablet)
- Add i18n counter keys for en/uk/pl with ICU plural forms
- Fix threshold bug: violations warning now triggers at 4+ (was 3+)
  to match actual integrity score calculation (100 - violations * 10 < 70)

* fix(quiz): fix points mismatch between leaderboard and dashboard

Dashboard showed raw pointsEarned from last quiz_attempt, while
leaderboard summed improvement deltas from point_transactions.
Additionally, orphaned transactions from re-seeded quizzes inflated
leaderboard totals (12 rows, 83 ghost points cleaned up in DB).

- Dashboard query now joins point_transactions to show actual awarded
  points per quiz instead of raw attempt score
- Leaderboard query filters out orphaned transactions where the
  source attempt no longer exists in quiz_attempts

* OBfix(quiz): fix points mismatch, consistent status badges, mobile UX

Dashboard showed raw pointsEarned from last attempt while leaderboard
summed improvement deltas from point_transactions. Orphaned transactions
from re-seeded quizzes inflated leaderboard totals (cleaned up in DB).

- Dashboard query joins point_transactions for actual awarded points
- Leaderboard query filters orphaned transactions (source_id not in quiz_attempts)
- Quiz cards use 3-level badges (Mastered/Review/Study) matching dashboard
- Mobile quiz results show dash for zero points, added chevron indicator

* fix(quiz): add breadcrumbs to review page, fix recommendation tautology

* fix(quiz): align result messages with status badges, persist result on locale switch

* chore(release): v1.0.0

---------

Co-authored-by: tetiana zorii <tanyusha.zoriy@gmail.com>
Co-authored-by: Lesia Soloviova <106915140+LesiaUKR@users.noreply.github.com>
Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@users.noreply.github.com>
Co-authored-by: Yevhenii Datsenko <134847096+yevheniidatsenko@users.noreply.github.com>
Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com>
ViktorSvertoka added a commit that referenced this pull request Feb 14, 2026
* feat(mobile): improve dashboard, leaderboard & AI helper UX for touch devices

  - Add touch drag support for AI helper modal and explained terms reorder
  - Position explain button below selected word on mobile
  - Show delete/restore buttons always visible on mobile (no hover)
  - Add user avatar to dashboard profile card (same as leaderboard)
  - Fix leaderboard page layout
  - Fix Tailwind v4 canonical class warnings

* Added touchcancel listener

* (SP: 2) [Frontend] Quiz results dashboard, review cache fix, UX improvements (#317)

* (SP: 3) [Backend] add internal janitor (jobs 1-4), claim/lease + runbook (G0-G6) (#318)

* (SP: 2) [Frontend] Redesign Home Hero & Add Features Section (#319)

* refactor(home): rename hero sections and add complete i18n support

- Rename LegacyHeroSection → WelcomeHeroSection
- Rename HeroSection → FeaturesHeroSection
- Add welcomeDescription translation key to eliminate duplication
- Translate all hardcoded text (headings, badges, CTAs)
- Improve Ukrainian/Polish translations for better readability
- Remove unused legacy components and images

* feat(about): update LinkedIn follower count to reflect current stat (1.5k+)

* refactor(home): implement i18n for FlipCardQA & fix memory leaks

* fix(home): resolve rotateY conflict & scope keyboard events in FlipCardQA

* fix(home): resolve all issues

* chore(home): cleanup comments, remove dead code & fix trailing spaces

* (SP: 2) [Frontend] Quiz UX improvements: violations counter, breadcrumbs, status badges (#320)

* feat(quiz): add guest warning before start and bot protection

Guest warning: show login/signup/continue buttons for unauthenticated
users on quiz rules screen before starting.

Bot protection: multi-attempt verification via Redis - each question
can only be verified once per user per attempt. Keys use dynamic TTL
matching quiz time limit and are cleared on retake.

Additional fixes:
- Footer flash on quiz navigation (added loading.tsx, eliminated redirect)
- Renamed QaLoader to Loader for reuse across pages
- React compiler purity errors (crypto.getRandomValues in handlers)
- Start button disabled after retake (isStarting not reset)

* refactor(quiz): PR review feedback

- Extract shared resolveRequestIdentifier() helper to eliminate
  duplicated auth/IP resolution logic in route.ts and actions/quiz.ts
- Return null instead of 'unknown' when identifier unresolvable,
  skip verification tracking for unidentifiable users
- Cap Redis TTL with MAX_TTL (3600s) to prevent client-supplied
  timeLimitSeconds from persisting keys indefinitely
- Add locale prefix to returnTo paths in guest warning links
- Replace nested Button inside Link with styled Link to fix
  invalid HTML (interactive element nesting)

* fix(quiz): fall through to IP when auth cookie is expired/invalid

* feat(quiz): add quiz results dashboard and review page

- Add quiz history section to dashboard with last attempt per quiz
- Add review page showing incorrect questions with explanations
- Add collapsible cards with expand/collapse all toggle
- Add "Review Mistakes" button on quiz result screen
- Add category icons to quiz page and review page headers
- Add BookOpen icon to explanation block in QuizQuestion
- Update guest message to mention error review benefit
- Add i18n translations (en/uk/pl) for all new features

* fix(quiz): scroll to next button on answer reveal, scope review cache by userId

* fix(quiz): restore type imports and userId cache key after merge conflict

* fix: restore type imports, sync @swc/helpers, fix indentation after merge

* feat(quiz): add violations counter UI, fix disqualification threshold

- Add ViolationsCounter component with color escalation (green/yellow/red)
- Sticky top bar keeps counter visible on scroll (mobile/tablet)
- Add i18n counter keys for en/uk/pl with ICU plural forms
- Fix threshold bug: violations warning now triggers at 4+ (was 3+)
  to match actual integrity score calculation (100 - violations * 10 < 70)

* fix(quiz): fix points mismatch between leaderboard and dashboard

Dashboard showed raw pointsEarned from last quiz_attempt, while
leaderboard summed improvement deltas from point_transactions.
Additionally, orphaned transactions from re-seeded quizzes inflated
leaderboard totals (12 rows, 83 ghost points cleaned up in DB).

- Dashboard query now joins point_transactions to show actual awarded
  points per quiz instead of raw attempt score
- Leaderboard query filters out orphaned transactions where the
  source attempt no longer exists in quiz_attempts

* OBfix(quiz): fix points mismatch, consistent status badges, mobile UX

Dashboard showed raw pointsEarned from last attempt while leaderboard
summed improvement deltas from point_transactions. Orphaned transactions
from re-seeded quizzes inflated leaderboard totals (cleaned up in DB).

- Dashboard query joins point_transactions for actual awarded points
- Leaderboard query filters orphaned transactions (source_id not in quiz_attempts)
- Quiz cards use 3-level badges (Mastered/Review/Study) matching dashboard
- Mobile quiz results show dash for zero points, added chevron indicator

* fix(quiz): add breadcrumbs to review page, fix recommendation tautology

* Header UX polish, quiz highlight fix, Blog button styling, shop i18n product    descriptions (#322)

* Header UX: reorder languages, swap controls, fix quiz highlight, style Blog button

* shop i18n product descriptions

* (SP: 1) [Frontend] Q&A: Next.js tab states + faster loader start (#324)

* fix(qa): align Next.js tab states and speed up loader startup

* feat(home,qa): improve home snap flow and add configurable Q&A page size

* fix(i18n,qa,seed): address review issues for locale handling and pagination state

* (SP: 1) [Frontend] Align quiz result messages with status badges, fix locale switch on result page (#325)

* feat(quiz): add guest warning before start and bot protection

Guest warning: show login/signup/continue buttons for unauthenticated
users on quiz rules screen before starting.

Bot protection: multi-attempt verification via Redis - each question
can only be verified once per user per attempt. Keys use dynamic TTL
matching quiz time limit and are cleared on retake.

Additional fixes:
- Footer flash on quiz navigation (added loading.tsx, eliminated redirect)
- Renamed QaLoader to Loader for reuse across pages
- React compiler purity errors (crypto.getRandomValues in handlers)
- Start button disabled after retake (isStarting not reset)

* refactor(quiz): PR review feedback

- Extract shared resolveRequestIdentifier() helper to eliminate
  duplicated auth/IP resolution logic in route.ts and actions/quiz.ts
- Return null instead of 'unknown' when identifier unresolvable,
  skip verification tracking for unidentifiable users
- Cap Redis TTL with MAX_TTL (3600s) to prevent client-supplied
  timeLimitSeconds from persisting keys indefinitely
- Add locale prefix to returnTo paths in guest warning links
- Replace nested Button inside Link with styled Link to fix
  invalid HTML (interactive element nesting)

* fix(quiz): fall through to IP when auth cookie is expired/invalid

* feat(quiz): add quiz results dashboard and review page

- Add quiz history section to dashboard with last attempt per quiz
- Add review page showing incorrect questions with explanations
- Add collapsible cards with expand/collapse all toggle
- Add "Review Mistakes" button on quiz result screen
- Add category icons to quiz page and review page headers
- Add BookOpen icon to explanation block in QuizQuestion
- Update guest message to mention error review benefit
- Add i18n translations (en/uk/pl) for all new features

* fix(quiz): scroll to next button on answer reveal, scope review cache by userId

* fix(quiz): restore type imports and userId cache key after merge conflict

* fix: restore type imports, sync @swc/helpers, fix indentation after merge

* feat(quiz): add violations counter UI, fix disqualification threshold

- Add ViolationsCounter component with color escalation (green/yellow/red)
- Sticky top bar keeps counter visible on scroll (mobile/tablet)
- Add i18n counter keys for en/uk/pl with ICU plural forms
- Fix threshold bug: violations warning now triggers at 4+ (was 3+)
  to match actual integrity score calculation (100 - violations * 10 < 70)

* fix(quiz): fix points mismatch between leaderboard and dashboard

Dashboard showed raw pointsEarned from last quiz_attempt, while
leaderboard summed improvement deltas from point_transactions.
Additionally, orphaned transactions from re-seeded quizzes inflated
leaderboard totals (12 rows, 83 ghost points cleaned up in DB).

- Dashboard query now joins point_transactions to show actual awarded
  points per quiz instead of raw attempt score
- Leaderboard query filters out orphaned transactions where the
  source attempt no longer exists in quiz_attempts

* OBfix(quiz): fix points mismatch, consistent status badges, mobile UX

Dashboard showed raw pointsEarned from last attempt while leaderboard
summed improvement deltas from point_transactions. Orphaned transactions
from re-seeded quizzes inflated leaderboard totals (cleaned up in DB).

- Dashboard query joins point_transactions for actual awarded points
- Leaderboard query filters orphaned transactions (source_id not in quiz_attempts)
- Quiz cards use 3-level badges (Mastered/Review/Study) matching dashboard
- Mobile quiz results show dash for zero points, added chevron indicator

* fix(quiz): add breadcrumbs to review page, fix recommendation tautology

* fix(quiz): align result messages with status badges, persist result on locale switch

* chore(release): v1.0.0

* feat(jpg): add images for shop

---------

Co-authored-by: tetiana zorii <tanyusha.zoriy@gmail.com>
Co-authored-by: Lesia Soloviova <106915140+LesiaUKR@users.noreply.github.com>
Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@users.noreply.github.com>
Co-authored-by: Yevhenii Datsenko <134847096+yevheniidatsenko@users.noreply.github.com>
Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com>
ViktorSvertoka added a commit that referenced this pull request Feb 15, 2026
* feat(mobile): improve dashboard, leaderboard & AI helper UX for touch devices

  - Add touch drag support for AI helper modal and explained terms reorder
  - Position explain button below selected word on mobile
  - Show delete/restore buttons always visible on mobile (no hover)
  - Add user avatar to dashboard profile card (same as leaderboard)
  - Fix leaderboard page layout
  - Fix Tailwind v4 canonical class warnings

* Added touchcancel listener

* (SP: 2) [Frontend] Quiz results dashboard, review cache fix, UX improvements (#317)

* (SP: 3) [Backend] add internal janitor (jobs 1-4), claim/lease + runbook (G0-G6) (#318)

* (SP: 2) [Frontend] Redesign Home Hero & Add Features Section (#319)

* refactor(home): rename hero sections and add complete i18n support

- Rename LegacyHeroSection → WelcomeHeroSection
- Rename HeroSection → FeaturesHeroSection
- Add welcomeDescription translation key to eliminate duplication
- Translate all hardcoded text (headings, badges, CTAs)
- Improve Ukrainian/Polish translations for better readability
- Remove unused legacy components and images

* feat(about): update LinkedIn follower count to reflect current stat (1.5k+)

* refactor(home): implement i18n for FlipCardQA & fix memory leaks

* fix(home): resolve rotateY conflict & scope keyboard events in FlipCardQA

* fix(home): resolve all issues

* chore(home): cleanup comments, remove dead code & fix trailing spaces

* (SP: 2) [Frontend] Quiz UX improvements: violations counter, breadcrumbs, status badges (#320)

* feat(quiz): add guest warning before start and bot protection

Guest warning: show login/signup/continue buttons for unauthenticated
users on quiz rules screen before starting.

Bot protection: multi-attempt verification via Redis - each question
can only be verified once per user per attempt. Keys use dynamic TTL
matching quiz time limit and are cleared on retake.

Additional fixes:
- Footer flash on quiz navigation (added loading.tsx, eliminated redirect)
- Renamed QaLoader to Loader for reuse across pages
- React compiler purity errors (crypto.getRandomValues in handlers)
- Start button disabled after retake (isStarting not reset)

* refactor(quiz): PR review feedback

- Extract shared resolveRequestIdentifier() helper to eliminate
  duplicated auth/IP resolution logic in route.ts and actions/quiz.ts
- Return null instead of 'unknown' when identifier unresolvable,
  skip verification tracking for unidentifiable users
- Cap Redis TTL with MAX_TTL (3600s) to prevent client-supplied
  timeLimitSeconds from persisting keys indefinitely
- Add locale prefix to returnTo paths in guest warning links
- Replace nested Button inside Link with styled Link to fix
  invalid HTML (interactive element nesting)

* fix(quiz): fall through to IP when auth cookie is expired/invalid

* feat(quiz): add quiz results dashboard and review page

- Add quiz history section to dashboard with last attempt per quiz
- Add review page showing incorrect questions with explanations
- Add collapsible cards with expand/collapse all toggle
- Add "Review Mistakes" button on quiz result screen
- Add category icons to quiz page and review page headers
- Add BookOpen icon to explanation block in QuizQuestion
- Update guest message to mention error review benefit
- Add i18n translations (en/uk/pl) for all new features

* fix(quiz): scroll to next button on answer reveal, scope review cache by userId

* fix(quiz): restore type imports and userId cache key after merge conflict

* fix: restore type imports, sync @swc/helpers, fix indentation after merge

* feat(quiz): add violations counter UI, fix disqualification threshold

- Add ViolationsCounter component with color escalation (green/yellow/red)
- Sticky top bar keeps counter visible on scroll (mobile/tablet)
- Add i18n counter keys for en/uk/pl with ICU plural forms
- Fix threshold bug: violations warning now triggers at 4+ (was 3+)
  to match actual integrity score calculation (100 - violations * 10 < 70)

* fix(quiz): fix points mismatch between leaderboard and dashboard

Dashboard showed raw pointsEarned from last quiz_attempt, while
leaderboard summed improvement deltas from point_transactions.
Additionally, orphaned transactions from re-seeded quizzes inflated
leaderboard totals (12 rows, 83 ghost points cleaned up in DB).

- Dashboard query now joins point_transactions to show actual awarded
  points per quiz instead of raw attempt score
- Leaderboard query filters out orphaned transactions where the
  source attempt no longer exists in quiz_attempts

* OBfix(quiz): fix points mismatch, consistent status badges, mobile UX

Dashboard showed raw pointsEarned from last attempt while leaderboard
summed improvement deltas from point_transactions. Orphaned transactions
from re-seeded quizzes inflated leaderboard totals (cleaned up in DB).

- Dashboard query joins point_transactions for actual awarded points
- Leaderboard query filters orphaned transactions (source_id not in quiz_attempts)
- Quiz cards use 3-level badges (Mastered/Review/Study) matching dashboard
- Mobile quiz results show dash for zero points, added chevron indicator

* fix(quiz): add breadcrumbs to review page, fix recommendation tautology

* Header UX polish, quiz highlight fix, Blog button styling, shop i18n product    descriptions (#322)

* Header UX: reorder languages, swap controls, fix quiz highlight, style Blog button

* shop i18n product descriptions

* (SP: 1) [Frontend] Q&A: Next.js tab states + faster loader start (#324)

* fix(qa): align Next.js tab states and speed up loader startup

* feat(home,qa): improve home snap flow and add configurable Q&A page size

* fix(i18n,qa,seed): address review issues for locale handling and pagination state

* (SP: 1) [Frontend] Align quiz result messages with status badges, fix locale switch on result page (#325)

* feat(quiz): add guest warning before start and bot protection

Guest warning: show login/signup/continue buttons for unauthenticated
users on quiz rules screen before starting.

Bot protection: multi-attempt verification via Redis - each question
can only be verified once per user per attempt. Keys use dynamic TTL
matching quiz time limit and are cleared on retake.

Additional fixes:
- Footer flash on quiz navigation (added loading.tsx, eliminated redirect)
- Renamed QaLoader to Loader for reuse across pages
- React compiler purity errors (crypto.getRandomValues in handlers)
- Start button disabled after retake (isStarting not reset)

* refactor(quiz): PR review feedback

- Extract shared resolveRequestIdentifier() helper to eliminate
  duplicated auth/IP resolution logic in route.ts and actions/quiz.ts
- Return null instead of 'unknown' when identifier unresolvable,
  skip verification tracking for unidentifiable users
- Cap Redis TTL with MAX_TTL (3600s) to prevent client-supplied
  timeLimitSeconds from persisting keys indefinitely
- Add locale prefix to returnTo paths in guest warning links
- Replace nested Button inside Link with styled Link to fix
  invalid HTML (interactive element nesting)

* fix(quiz): fall through to IP when auth cookie is expired/invalid

* feat(quiz): add quiz results dashboard and review page

- Add quiz history section to dashboard with last attempt per quiz
- Add review page showing incorrect questions with explanations
- Add collapsible cards with expand/collapse all toggle
- Add "Review Mistakes" button on quiz result screen
- Add category icons to quiz page and review page headers
- Add BookOpen icon to explanation block in QuizQuestion
- Update guest message to mention error review benefit
- Add i18n translations (en/uk/pl) for all new features

* fix(quiz): scroll to next button on answer reveal, scope review cache by userId

* fix(quiz): restore type imports and userId cache key after merge conflict

* fix: restore type imports, sync @swc/helpers, fix indentation after merge

* feat(quiz): add violations counter UI, fix disqualification threshold

- Add ViolationsCounter component with color escalation (green/yellow/red)
- Sticky top bar keeps counter visible on scroll (mobile/tablet)
- Add i18n counter keys for en/uk/pl with ICU plural forms
- Fix threshold bug: violations warning now triggers at 4+ (was 3+)
  to match actual integrity score calculation (100 - violations * 10 < 70)

* fix(quiz): fix points mismatch between leaderboard and dashboard

Dashboard showed raw pointsEarned from last quiz_attempt, while
leaderboard summed improvement deltas from point_transactions.
Additionally, orphaned transactions from re-seeded quizzes inflated
leaderboard totals (12 rows, 83 ghost points cleaned up in DB).

- Dashboard query now joins point_transactions to show actual awarded
  points per quiz instead of raw attempt score
- Leaderboard query filters out orphaned transactions where the
  source attempt no longer exists in quiz_attempts

* OBfix(quiz): fix points mismatch, consistent status badges, mobile UX

Dashboard showed raw pointsEarned from last attempt while leaderboard
summed improvement deltas from point_transactions. Orphaned transactions
from re-seeded quizzes inflated leaderboard totals (cleaned up in DB).

- Dashboard query joins point_transactions for actual awarded points
- Leaderboard query filters orphaned transactions (source_id not in quiz_attempts)
- Quiz cards use 3-level badges (Mastered/Review/Study) matching dashboard
- Mobile quiz results show dash for zero points, added chevron indicator

* fix(quiz): add breadcrumbs to review page, fix recommendation tautology

* fix(quiz): align result messages with status badges, persist result on locale switch

* chore(release): v1.0.0

* feat(jpg): add images for shop

* (SP: 3) [Shop][Monobank] Janitor map + internal janitor endpoint stub + status UX + security/obs + J test gate (#328)

* (SP: 3) [Backend] add internal janitor (jobs 1-4), claim/lease + runbook (G0-G6)

* (SP: 3) [Backend] add provider selector, fix payments gating, i18n checkout errors

* Add shop category images to public

* (SP: 3) [Shop][Monobank] I1 structured logging: codes + logging safety checks

* (SP: 3) [Shop][Monobank] Fail-closed non-browser origin posture for webhook + janitor (ORIGIN_BLOCKED)

* (SP: 3) [Shop][Monobank] [Shop][Monobank] J gate: add orders status ownership test and pass all pre-prod invariants

* (SP: 3) [Shop][Monobank]  review fixes (tests, logging, success UI)

* (SP: 1) [Shop][Monobank] Tighten webhook log-code typing; harden DB tests; minor security/log/UI cleanups

* (SP: 1) [Shop][Monobank] harden Monobank webhook (origin/PII-safe logs) and remove duplicate sha256 hashing

* (SP:2) [Frontend] Fix duplicated Q&A items after content updates (#330)

* fix(qa): prevent duplicate questions and improve cache invalidation

* fix(qa): keep pagination totals consistent after deduplication

* (SP: 1) [Frontend] Integrate online users counter popup and fix header (#331)

* feat(home): add online users counter + fix header breakpoint

* deleted scrollY in OnlineCounterPopup

* fixed fetch in OnlineCounterPopup

* Bug/fix qa (#332)

* fix(qa): prevent duplicate questions and improve cache invalidation

* fix(qa): keep pagination totals consistent after deduplication

* fix(qa): paginate by unique questions and bump cache namespace

* chore(release): v1.0.1

---------

Co-authored-by: tetiana zorii <tanyusha.zoriy@gmail.com>
Co-authored-by: Lesia Soloviova <106915140+LesiaUKR@users.noreply.github.com>
Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@users.noreply.github.com>
Co-authored-by: Yevhenii Datsenko <134847096+yevheniidatsenko@users.noreply.github.com>
Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com>
Co-authored-by: Yuliia Nazymko <122815071+YNazymko12@users.noreply.github.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

Development

Successfully merging this pull request may close these issues.

2 participants