Skip to content

(SP: 3) [AI] Add AI word helper with Groq integration#200

Merged
ViktorSvertoka merged 2 commits into
developfrom
feature/ai-word-helper
Jan 25, 2026
Merged

(SP: 3) [AI] Add AI word helper with Groq integration#200
ViktorSvertoka merged 2 commits into
developfrom
feature/ai-word-helper

Conversation

@TiZorii
Copy link
Copy Markdown
Collaborator

@TiZorii TiZorii commented Jan 25, 2026

  • Implement Groq API with Llama 3.1 70B model
  • Add text selection detection on Q&A page
  • Create floating "Explain" button
  • Build draggable modal with 3-language support (uk/en/pl)
  • Add localStorage caching for instant repeated lookups
  • Implement guest CTA (login/signup)
  • Add rate limiting (10 requests/20 min)
  • Auth-gated feature (registered users only)

Components:

  • SelectableText: Detects text selection
  • FloatingExplainButton: Appears on selection
  • AIWordHelper: Main modal with explanations

Summary by CodeRabbit

  • New Features
    • AI-powered explanation tool: selectable text, floating explain button, draggable multilingual modal (uk/en/pl), caching, and guest/auth flows.
  • Localization
    • Added aiHelper UI strings; removed legacy "about" section from translations; default locale switched to English.
  • User Experience
    • Improved rate-limit and service-error messaging with retry guidance.
  • Chores
    • Added GROQ SDK dependency.

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

- Implement Groq API with Llama 3.1 70B model
- Add text selection detection on Q&A page
- Create floating "Explain" button
- Build draggable modal with 3-language support (uk/en/pl)
- Add localStorage caching for instant repeated lookups
- Implement guest CTA (login/signup)
- Add rate limiting (10 requests/min)
- Auth-gated feature (registered users only)

Components:
- SelectableText: Detects text selection
- FloatingExplainButton: Appears on selection
- AIWordHelper: Main modal with explanations
@netlify
Copy link
Copy Markdown

netlify Bot commented Jan 25, 2026

Deploy Preview for develop-devlovers ready!

Name Link
🔨 Latest commit 3deb4fd
🔍 Latest deploy log https://app.netlify.com/projects/develop-devlovers/deploys/6975b5214e3ed100084d418e
😎 Deploy Preview https://deploy-preview-200--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 25, 2026

📝 Walkthrough

Walkthrough

Adds an AI-powered word explanation feature: a new POST API route for generating multilingual explanations (llama via GROQ), client-side selection UI and helper modal, caching, highlight integration into the Q&A accordion, translations, and related locale/default adjustments.

Changes

Cohort / File(s) Summary
Backend API Route
frontend/app/api/ai/explain/route.ts
New POST handler exposing /api/ai/explain with IP-based rate limiting, Zod request validation, client IP extraction, GROQ API integration (llama model), robust response parsing for uk,en,pl, structured error handling and rate-limit headers.
Frontend AI Cache & Prompts
frontend/lib/ai/explainCache.ts, frontend/lib/ai/prompts.ts
New explainCache: localStorage-backed, versioned cache APIs (get/set/clear/size/terms/has); prompts.ts: createExplainPrompt and ExplanationResponse interface for multilingual payloads.
AI Helper UI
frontend/components/q&a/AIWordHelper.tsx
Large new draggable modal component with auth check, locale switcher, client-side caching use, loading/error/rate-limit handling, formatted multilingual explanations, retry flows and guest CTAs.
Selection & Floating Controls
frontend/components/q&a/SelectableText.tsx, frontend/components/q&a/FloatingExplainButton.tsx
SelectableText: detects in-component text selections and reports screen position. FloatingExplainButton: anchored floating button with auto-dismiss on scroll/outside click and accessible interactions.
Highlighting Helper
frontend/components/q&a/HighlightCachedTerms.tsx
Renders text segmented by cached terms (word-boundary regex), clickable styled spans for cached terms, memoized segmentation and click callbacks.
Accordion Integration
frontend/components/q&a/AccordionList.tsx
Threads HighlightContext through renderers, wraps content in SelectableText, integrates FloatingExplainButton and AIWordHelper, uses HighlightCachedTerms, storage-sync for cached terms, and adjusts render pipeline for highlight-aware rendering.
Translations
frontend/messages/en.json, frontend/messages/pl.json, frontend/messages/uk.json
Removed existing about section keys and added new top-level aiHelper translation entries (button text, modal, loading/error, languages, guest, rateLimit, serviceError).
Locale & Proxy Defaults
frontend/i18n/config.ts, frontend/proxy.ts
Default locale changed from uk to en; proxy/middleware redirects and fallback locales updated accordingly.
Dependencies
frontend/package.json
Added runtime dependency groq-sdk (^0.37.0).

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant SelectableText as SelectableText (Component)
    participant FloatingButton as FloatingExplainButton (Component)
    participant AIHelper as AIWordHelper (Component)
    participant Cache as explainCache (LocalStorage)
    participant APIRoute as /api/ai/explain (Route)
    participant GROQ as GROQ API

    User->>SelectableText: select text
    SelectableText->>FloatingButton: report selection & position
    FloatingButton->>User: show explain button
    User->>FloatingButton: click explain
    FloatingButton->>AIHelper: open modal with term

    AIHelper->>Cache: getCachedExplanation(term)
    alt cache hit
        Cache-->>AIHelper: explanation
        AIHelper->>User: render explanation
    else cache miss
        AIHelper->>APIRoute: POST { term, context }
        APIRoute->>APIRoute: validate & rate-limit (IP)
        APIRoute->>GROQ: request completion (llama)
        GROQ-->>APIRoute: completion (json)
        APIRoute->>APIRoute: parse & validate response
        APIRoute-->>AIHelper: explanation + rate-limit headers
        AIHelper->>Cache: setCachedExplanation(term, explanation)
        AIHelper->>User: render explanation
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • AM1007
  • ViktorSvertoka

Poem

🐰 With twitching nose I hop and peep,

I find the words you could not keep.
I fetch the cache, I ask the grove,
Three tongues reply — now learn and rove.
A tiny rabbit's helpful leap. 🥕

🚥 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 PR title accurately summarizes the main change: adding an AI word helper feature with Groq integration. It is concise, clear, and directly reflects the primary objective of the changeset.

✏️ 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: 5

🤖 Fix all issues with AI agents
In `@frontend/app/api/ai/explain/route.ts`:
- Around line 9-12: The rate limit window constant RATE_LIMIT_WINDOW_MS is set
to 20 minutes (20 * 60 * 1000) but the PR requires 10 requests per minute;
update RATE_LIMIT_WINDOW_MS to represent 1 minute (60 * 1000) so that the
existing rateLimiter/ MAX_REQUESTS_PER_WINDOW logic enforces 10 requests per
minute for the Map<string, { count: number; resetAt: number }> tracking.

In `@frontend/components/q`&a/AIWordHelper.tsx:
- Around line 125-131: Guard against unsupported locale values by validating
params.locale before casting and setting activeLocale; in AIWordHelper.tsx use
the value from useParams() and check it exists in messagesByLocale (or the
Locale enum) and only then call setActiveLocale or initialize the state,
otherwise fall back to a safe default like 'uk'. Update the initialization of
activeLocale and any places reading explanation[activeLocale] to use the
validated/fallback locale (useParams, activeLocale, setActiveLocale,
messagesByLocale, explanation) so invalid params.locale cannot index into
messagesByLocale or explanation.

In `@frontend/lib/ai/explainCache.ts`:
- Around line 24-45: The readCache function may return parsed JSON whose shape
is invalid (e.g., data.entries is undefined) causing downstream crashes; update
readCache (and its use of CACHE_VERSION and CACHE_KEY) to validate the parsed
object before returning: after parsing JSON into data (as CacheData) check that
data is a non-null object, data.version === CACHE_VERSION (or handle legacy
versions as already done) and that typeof data.entries === 'object' &&
data.entries !== null; if the shape is invalid remove the cached item from
localStorage and return the default { version: CACHE_VERSION, entries: {} } so
malformed or legacy data is reset safely.

In `@frontend/messages/pl.json`:
- Around line 350-395: The new aiHelper localization keys contain missing Polish
diacritics; update the values under the "aiHelper" object (e.g., buttonText,
modalTitle, term, loading, error, retry, guest.title/description/login/signup,
rateLimit.hint/tryLater/persistent/persistentHint/patience/takingBreak/whileWaiting/starGithubHint/takeQuiz/takeQuizHint/writeReview/writeReviewHint,
and serviceError.title/hint/tryAgain/persistent/persistentHint/working/fixing)
to use proper Polish characters (e.g., Wyjaśnij, Wyjaśnienie, nie udało się,
Spróbuj, Cierpliwość, Dołącz, za chwilę, wkrótce wróci, recenzję, etc.); keep
the keys unchanged and only correct the string values so translations remain
accurate and consistent.

In `@frontend/package.json`:
- Around line 39-41: Update frontend/package.json to add a top-level "engines"
field enforcing Node.js >=18 (e.g., "engines": { "node": ">=18" }) so installs
fail on older Node versions required by groq-sdk@0.37.0; insert the "engines"
object alongside existing top-level fields (near
"dependencies"/"devDependencies") and commit the change, then run a local
install to verify the engine check prevents installation on Node <18.
🧹 Nitpick comments (8)
frontend/messages/en.json (1)

357-361: Language label "UK" may confuse users.

In the English locale, "uk": "UK" could be mistaken for "United Kingdom" rather than "Ukrainian". Consider using "UA" (as done in uk.json line 359) or "Ukr" for clarity in the English locale.

     "languages": {
-      "uk": "UK",
+      "uk": "UA",
       "en": "EN",
       "pl": "PL"
     },
frontend/components/q&a/FloatingExplainButton.tsx (1)

21-42: Consider stabilizing onDismiss or document the memoization requirement.

The useEffect depends on onDismiss, so if the parent component passes an inline function, listeners will be torn down and re-attached on every render. This could cause flickering or missed events.

Either:

  1. Document that onDismiss should be memoized with useCallback in the parent, or
  2. Use a ref to capture the latest callback without triggering effect re-runs:
♻️ Alternative using ref
+ const onDismissRef = useRef(onDismiss);
+ onDismissRef.current = onDismiss;

  useEffect(() => {
    const handleScroll = () => {
-     onDismiss();
+     onDismissRef.current();
    };

    const handleClickOutside = (e: MouseEvent) => {
      if (buttonRef.current && !buttonRef.current.contains(e.target as Node)) {
-       onDismiss();
+       onDismissRef.current();
      }
    };
    // ... rest unchanged
-  }, [onDismiss]);
+  }, []);
frontend/lib/ai/prompts.ts (1)

6-18: Consider sanitizing or validating the term input.

The term is interpolated directly into the prompt multiple times. While the LLM should handle this gracefully, extremely long terms or terms containing prompt-like instructions could affect output quality or token consumption.

Consider adding basic validation:

♻️ Suggested validation
 export function createExplainPrompt({
   term,
   context,
 }: ExplainPromptParams): string {
+  // Basic validation
+  const sanitizedTerm = term.slice(0, 100).trim();
+  const sanitizedContext = context?.slice(0, 500).trim();
+
   const contextLine = context
-    ? `Context where the term appears: "${context}"`
+    ? `Context where the term appears: "${sanitizedContext}"`
     : 'No additional context provided.';
frontend/components/q&a/SelectableText.tsx (2)

20-55: Missing keyboard-based selection support.

The component only handles onMouseUp, which means users who select text using keyboard (Shift+Arrow keys) won't trigger the floating button. Consider adding a onKeyUp handler for accessibility.

♻️ Suggested enhancement
- const handleMouseUp = useCallback(() => {
+ const handleSelectionChange = useCallback(() => {
    setTimeout(() => {
      const selection = window.getSelection();
      // ... rest unchanged
    }, 10);
  }, [onTextSelect, onSelectionClear, minSelectionLength]);

  return (
-   <div ref={containerRef} onMouseUp={handleMouseUp} className="cursor-text">
+   <div
+     ref={containerRef}
+     onMouseUp={handleSelectionChange}
+     onKeyUp={handleSelectionChange}
+     className="cursor-text"
+   >
      {children}
    </div>
  );

36-51: Minor: getRangeAt(0) is called twice.

The range is fetched at line 37 for containment check and again at line 45 for position calculation. Consider reusing the first range.

♻️ Suggested fix
      if (containerRef.current) {
        const range = selection.getRangeAt(0);
        const selectionContainer = range.commonAncestorContainer;

        if (!containerRef.current.contains(selectionContainer)) {
          return;
        }
-     }
-
-     const range = selection.getRangeAt(0);
-     const rect = range.getBoundingClientRect();
+       const rect = range.getBoundingClientRect();

-     const position = {
-       x: rect.left + rect.width / 2,
-       y: rect.top,
-     };
+       const position = {
+         x: rect.left + rect.width / 2,
+         y: rect.top,
+       };

-     onTextSelect(selectedText, position);
+       onTextSelect(selectedText, position);
+     }
frontend/components/q&a/HighlightCachedTerms.tsx (1)

77-96: Clickable spans lack keyboard accessibility.

The cached term spans are clickable but not keyboard-focusable. Consider adding tabIndex={0} and an onKeyDown handler for Enter/Space keys to make them accessible.

♻️ Suggested enhancement
          <span
            key={index}
            onClick={e => {
              e.stopPropagation();
              onTermClick?.(segment.originalTerm || segment.text);
            }}
+           onKeyDown={e => {
+             if (e.key === 'Enter' || e.key === ' ') {
+               e.preventDefault();
+               onTermClick?.(segment.originalTerm || segment.text);
+             }
+           }}
+           tabIndex={0}
+           role="button"
            className={cn(
              'cursor-pointer',
              // ... rest unchanged
            )}
            title="Click to see explanation (cached)"
+           aria-label={`Explain ${segment.text}`}
          >
frontend/app/api/ai/explain/route.ts (1)

39-45: Consider reusing the shared IP extraction helper.
There’s already getClientIp in frontend/lib/security/rate-limit.ts; reusing it avoids drift in header parsing behavior.

frontend/components/q&a/AccordionList.tsx (1)

316-320: Avoid hard-coded cache key in storage listener.
Consider exporting the cache key (or a helper) from explainCache.ts to prevent drift if the key changes.

Comment on lines +9 to +12
const rateLimiter = new Map<string, { count: number; resetAt: number }>();
const MAX_REQUESTS_PER_WINDOW = 10;
const RATE_LIMIT_WINDOW_MS = 20 * 60 * 1000;

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 | 🟠 Major

Rate-limit window is 20 minutes, not 1 minute.
PR objective says 10 requests/minute; current constant enforces 10 per 20 minutes.

🛠️ Align with 10/min
-const RATE_LIMIT_WINDOW_MS = 20 * 60 * 1000; 
+const RATE_LIMIT_WINDOW_MS = 60 * 1000;
📝 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
const rateLimiter = new Map<string, { count: number; resetAt: number }>();
const MAX_REQUESTS_PER_WINDOW = 10;
const RATE_LIMIT_WINDOW_MS = 20 * 60 * 1000;
const rateLimiter = new Map<string, { count: number; resetAt: number }>();
const MAX_REQUESTS_PER_WINDOW = 10;
const RATE_LIMIT_WINDOW_MS = 60 * 1000;
🤖 Prompt for AI Agents
In `@frontend/app/api/ai/explain/route.ts` around lines 9 - 12, The rate limit
window constant RATE_LIMIT_WINDOW_MS is set to 20 minutes (20 * 60 * 1000) but
the PR requires 10 requests per minute; update RATE_LIMIT_WINDOW_MS to represent
1 minute (60 * 1000) so that the existing rateLimiter/ MAX_REQUESTS_PER_WINDOW
logic enforces 10 requests per minute for the Map<string, { count: number;
resetAt: number }> tracking.

Comment thread frontend/components/q&amp;a/AIWordHelper.tsx
Comment on lines +24 to +45
function readCache(): CacheData {
if (!isBrowser()) {
return { version: CACHE_VERSION, entries: {} };
}

try {
const raw = localStorage.getItem(CACHE_KEY);
if (!raw) {
return { version: CACHE_VERSION, entries: {} };
}

const data = JSON.parse(raw) as CacheData;

if (data.version !== CACHE_VERSION) {
localStorage.removeItem(CACHE_KEY);
return { version: CACHE_VERSION, entries: {} };
}

return data;
} catch {
return { version: CACHE_VERSION, entries: {} };
}
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

Validate cache schema before returning parsed data.
If localStorage contains malformed/legacy JSON, cache.entries can be undefined and crash downstream. Add a shape guard and reset.

🛠️ Suggested guard
-    const data = JSON.parse(raw) as CacheData;
-
-    if (data.version !== CACHE_VERSION) {
+    const data = JSON.parse(raw) as Partial<CacheData>;
+
+    if (
+      typeof data.version !== 'number' ||
+      data.version !== CACHE_VERSION ||
+      !data.entries ||
+      typeof data.entries !== 'object'
+    ) {
       localStorage.removeItem(CACHE_KEY);
       return { version: CACHE_VERSION, entries: {} };
     }
 
-    return data;
+    return {
+      version: CACHE_VERSION,
+      entries: data.entries as Record<string, CacheEntry>,
+    };
🤖 Prompt for AI Agents
In `@frontend/lib/ai/explainCache.ts` around lines 24 - 45, The readCache function
may return parsed JSON whose shape is invalid (e.g., data.entries is undefined)
causing downstream crashes; update readCache (and its use of CACHE_VERSION and
CACHE_KEY) to validate the parsed object before returning: after parsing JSON
into data (as CacheData) check that data is a non-null object, data.version ===
CACHE_VERSION (or handle legacy versions as already done) and that typeof
data.entries === 'object' && data.entries !== null; if the shape is invalid
remove the cached item from localStorage and return the default { version:
CACHE_VERSION, entries: {} } so malformed or legacy data is reset safely.

Comment thread frontend/messages/pl.json
Comment thread frontend/package.json
Comment on lines 39 to 41
"groq": "^4.14.2",
"groq-sdk": "^0.37.0",
"jsonwebtoken": "^9.0.3",
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

🧩 Analysis chain

🌐 Web query:

groq-sdk version 0.37.0 Node.js requirements compatibility

💡 Result:

For groq-sdk@0.37.0, the project’s stated runtime requirement is:

  • Node.js: 18 LTS or later (non‑EOL versions). [1]

Other relevant compatibility notes:

  • TypeScript: >= 4.5. [1]
  • The published groq-sdk@0.37.0 package metadata does not declare an engines.node field in package.json (so npm/yarn won’t enforce a Node version automatically). [2]

Sources:
[1] (github.com)
[2] (cdn.jsdelivr.net)

Citations:


Add engines.node field to enforce Node.js 18 LTS minimum requirement.

The groq-sdk@0.37.0 package requires Node.js 18 LTS or later, but this version does not declare the engines.node field in its package.json. Add "engines": { "node": ">=18" } to frontend/package.json to enforce this requirement and prevent installation on incompatible Node versions.

🤖 Prompt for AI Agents
In `@frontend/package.json` around lines 39 - 41, Update frontend/package.json to
add a top-level "engines" field enforcing Node.js >=18 (e.g., "engines": {
"node": ">=18" }) so installs fail on older Node versions required by
groq-sdk@0.37.0; insert the "engines" object alongside existing top-level fields
(near "dependencies"/"devDependencies") and commit the change, then run a local
install to verify the engine check prevents installation on Node <18.

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: 0

Caution

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

⚠️ Outside diff range comments (1)
frontend/proxy.ts (1)

54-61: Fix locale extraction when the path lacks a locale.
For requests like /dashboard, pathname.split('/')[1] becomes "dashboard", so unauthenticated users get redirected to /dashboard/login, and x-locale becomes invalid. Extract locale via regex and fall back to 'en'.

🛠️ Proposed fix
-    const locale = pathname.split('/')[1] || 'en';
+    const locale =
+      pathname.match(/^\/(uk|en|pl)(?=\/|$)/)?.[1] ?? 'en';
     return NextResponse.redirect(new URL(`/${locale}/login`, req.url));
-  const locale = req.nextUrl.pathname.split('/')[1] || 'en';
+  const locale =
+    req.nextUrl.pathname.match(/^\/(uk|en|pl)(?=\/|$)/)?.[1] ?? 'en';

Also applies to: 75-80

🧹 Nitpick comments (1)
frontend/components/q&a/AIWordHelper.tsx (1)

15-52: Avoid bundling entire locale JSON files in this client component.
Importing @/messages/*.json pulls all namespaces and locales into the client bundle. Consider splitting aiHelper into smaller per-locale JSON modules or lazy-loading messages when the modal opens.

@ViktorSvertoka ViktorSvertoka merged commit a6f6bef into develop Jan 25, 2026
8 checks passed
@ViktorSvertoka ViktorSvertoka deleted the feature/ai-word-helper branch January 25, 2026 10:06
ViktorSvertoka added a commit that referenced this pull request Jan 25, 2026
* (SP: 1) [Security] Enforce origin posture for shop APIs (admin/checkout same-origin; internal/webhooks non-browser) + docs

* (SP: 1) [DB] Align stripe_events.order_id FK CASCADE across schema and migrations

* feat(i18n): localize quiz anti-cheat, header and blog filters (#175)

* feat(Blog): Adding last published post to the blog and category page, recommended posts, Changing styles to one unified format, Bug fixes

* Update leaderboard-style

* Update leaderboard-style

* teat(Blog): fix of hover on author, fix of the line

* (SP: 3) [Observability] Extend structured logging + correlation IDs across all shop routes; purge console.*; enforce explicit error codes

* (SP: 1) [Admin][Security] Add safe product delete (PRODUCT_IN_USE) + mobile cards UI; tighten env/docs, locale normalization, cache-control, and logging semantics

* fix: npm installing

* (SP: 1) [Admin] Align products list in use checks with DB column names (order_items/inventory_moves)

* fix:Update leaderboard: fixed background

* fix: remove email from CurrentUser type to prevent PII exposure

* refactor: align leaderboard UI with brand style (fixed bg, css vars, podium glow)

* (SP: 1) [Frontend] About Us Page. Fixed game, topics, mobile layout

- Fixed mobile tabs in FeaturesSection (icon-only on mobile)
- Fixed game bugs: collision detection, animation, scoring system
- Added multiple obstacle types with level progression
- Improved game sizing for mobile while preserving desktop
- Updated TopicsSection with local SVG icons and hover borders
- Made DynamicGridBackground static grid opt-in via showStaticGrid prop
- Limited SponsorsWall to display max 10 sponsors
- Optimized CommunitySection button layout for mobile

* refactor: update accent color hover effects to Footer

- Update Footer links to use --accent-primary on hover
- Update ThemeToggle icons to use --accent-primary on hover
- Both components adapt colors to light/dark theme

* refactor: improve accessibility

- Add focus-visible styles for keyboard navigation accessibility

* (SP: 1) [Shop] Fix Stripe checkout success redirect (remove duplicate locale /uk/uk) (#186)

* fix:leaderboard  update leaderboard-style (#187)

* fix:leaderboard update leaderboard-style on mobile (#188)

* fix:leaderboard  update leaderboard-style

* fix:leaderboard update leaderboard-style on mobile

* fix: resolve CodeRabbit issues and conflicts

---------

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

* (SP: 1) [Frontend] Changing hero headline on shop main page (#190)

* (SP: 1) [Shop] Fix checkout redirect 404 by removing duplicate locale in in-app routes and Stripe return_url

* (SP: 1) [Shop] Fix locale cart page and orderid page

* (SP: 1) [Frontend] Changin hero headline on shop main page

* (SP: 1) [Frontend] Fix styles shop home page, buttons (#191)

* Feature/leaderboard style update (#192)

* (SP: 7) [UI] Quiz UI polish: tabs styling, category accents, color scheme (#181, #193, #194) (#195)

* Sanity (#196)

* 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

* (SP: 3) [AI] Add AI word helper with Groq integration (#200)

* (SP: 3) [AI] Add AI word helper with Groq integration

- Implement Groq API with Llama 3.1 70B model
- Add text selection detection on Q&A page
- Create floating "Explain" button
- Build draggable modal with 3-language support (uk/en/pl)
- Add localStorage caching for instant repeated lookups
- Implement guest CTA (login/signup)
- Add rate limiting (10 requests/min)
- Auth-gated feature (registered users only)

Components:
- SelectableText: Detects text selection
- FloatingExplainButton: Appears on selection
- AIWordHelper: Main modal with explanations

* (SP: 1) i18n: fix Polish locale and set EN as default

* Sanity (#202)

* 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

* Sanity (#203)

* 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

* (SP: 3) [Frontend] Refactor Header UI and navigation states (#201)

* (SP: 3) [Frontend] Refactor Header UI and navigation states

- Add icon to the language switcher

- Add GitHub icon with stars indicator (frontend only)

- Update logo styles

- Improve touch interaction styles

- Verify correct placement and alignment of all header components

- Make mobile header modal full-screen

- Disable background scroll when mobile menu is open

- Highlight active navigation item

- Update navigation styles:

- Highlight Shop link when user is on Home pages
- Highlight Home link when user is on Shop pages
- Style changes only, no routing or logic changes

* fix CodeRabbit

* update HeaderButton styles

* fix: add accessibility for HeaderButton

* (SP: 3) [Testing] Vitest config + unit + integration tests for quiz module (#204)

* 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

* Feature/leaderboard style update (#206)

* fix:leaderboard  update leaderboard-style

* fix:leaderboard update leaderboard-style on mobile

* fix: resolve CodeRabbit issues and conflicts

* fix: move row border to first cell to resolve CodeRabbit issue

* fix: move row border to first cell to resolve CodeRabbit issue new

* fix(leaderboard): improve table mobile

* fix(leaderboard): correct malformed shadow class syntax for avatar glow

* test(q&a): add comprehensive qa tests and coverage setup (#208)

* test(q&a): add comprehensive qa tests and coverage setup

* test(q&a): align mocks and reset in qa tests

* (SP: 1) [Frontend] Remove Contacts References (#211)

* test(q&a): add comprehensive qa tests and coverage setup

* test(q&a): align mocks and reset in qa tests

* chore(nav): remove contacts page references

* Sanity (#209)

* 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

* chore(release): update changelog for v0.5.0

* chore(release): v0.5.0

---------

Co-authored-by: liudmylasovetovs <milkaegik@gmail.com>
Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com>
Co-authored-by: Anna <komrakova.anna@gmail.com>
Co-authored-by: AlinaRyabova <alinavr7@gmail.com>
Co-authored-by: Yevhenii Datsenko <yevheniydatsenko@gmail.com>
Co-authored-by: YNazymko12 <yulychka12@gmail.com>
Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@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: Yuliia Nazymko <122815071+YNazymko12@users.noreply.github.com>
ViktorSvertoka added a commit that referenced this pull request Jan 31, 2026
* (SP: 1) [Security] Enforce origin posture for shop APIs (admin/checkout same-origin; internal/webhooks non-browser) + docs

* (SP: 1) [DB] Align stripe_events.order_id FK CASCADE across schema and migrations

* feat(i18n): localize quiz anti-cheat, header and blog filters (#175)

* feat(Blog): Adding last published post to the blog and category page, recommended posts, Changing styles to one unified format, Bug fixes

* Update leaderboard-style

* Update leaderboard-style

* teat(Blog): fix of hover on author, fix of the line

* (SP: 3) [Observability] Extend structured logging + correlation IDs across all shop routes; purge console.*; enforce explicit error codes

* (SP: 1) [Admin][Security] Add safe product delete (PRODUCT_IN_USE) + mobile cards UI; tighten env/docs, locale normalization, cache-control, and logging semantics

* fix: npm installing

* (SP: 1) [Admin] Align products list in use checks with DB column names (order_items/inventory_moves)

* fix:Update leaderboard: fixed background

* fix: remove email from CurrentUser type to prevent PII exposure

* refactor: align leaderboard UI with brand style (fixed bg, css vars, podium glow)

* (SP: 1) [Frontend] About Us Page. Fixed game, topics, mobile layout

- Fixed mobile tabs in FeaturesSection (icon-only on mobile)
- Fixed game bugs: collision detection, animation, scoring system
- Added multiple obstacle types with level progression
- Improved game sizing for mobile while preserving desktop
- Updated TopicsSection with local SVG icons and hover borders
- Made DynamicGridBackground static grid opt-in via showStaticGrid prop
- Limited SponsorsWall to display max 10 sponsors
- Optimized CommunitySection button layout for mobile

* refactor: update accent color hover effects to Footer

- Update Footer links to use --accent-primary on hover
- Update ThemeToggle icons to use --accent-primary on hover
- Both components adapt colors to light/dark theme

* refactor: improve accessibility

- Add focus-visible styles for keyboard navigation accessibility

* (SP: 1) [Shop] Fix Stripe checkout success redirect (remove duplicate locale /uk/uk) (#186)

* fix:leaderboard  update leaderboard-style

* fix:leaderboard  update leaderboard-style (#187)

* fix:leaderboard update leaderboard-style on mobile

* fix: resolve CodeRabbit issues and conflicts

* fix:leaderboard update leaderboard-style on mobile (#188)

* fix:leaderboard  update leaderboard-style

* fix:leaderboard update leaderboard-style on mobile

* fix: resolve CodeRabbit issues and conflicts

---------

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

* (SP: 1) [Frontend] Changing hero headline on shop main page (#190)

* (SP: 1) [Shop] Fix checkout redirect 404 by removing duplicate locale in in-app routes and Stripe return_url

* (SP: 1) [Shop] Fix locale cart page and orderid page

* (SP: 1) [Frontend] Changin hero headline on shop main page

* (SP: 1) [Frontend] Fix styles shop home page, buttons (#191)

* fix: move row border to first cell to resolve CodeRabbit issue

* fix: move row border to first cell to resolve CodeRabbit issue new

* Feature/leaderboard style update (#192)

* (SP: 7) [UI] Quiz UI polish: tabs styling, category accents, color scheme (#181, #193, #194) (#195)

* Sanity (#196)

* 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

* (SP: 3) [AI] Add AI word helper with Groq integration (#200)

* (SP: 3) [AI] Add AI word helper with Groq integration

- Implement Groq API with Llama 3.1 70B model
- Add text selection detection on Q&A page
- Create floating "Explain" button
- Build draggable modal with 3-language support (uk/en/pl)
- Add localStorage caching for instant repeated lookups
- Implement guest CTA (login/signup)
- Add rate limiting (10 requests/min)
- Auth-gated feature (registered users only)

Components:
- SelectableText: Detects text selection
- FloatingExplainButton: Appears on selection
- AIWordHelper: Main modal with explanations

* (SP: 1) i18n: fix Polish locale and set EN as default

* Sanity (#202)

* 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

* Sanity (#203)

* 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

* (SP: 3) [Frontend] Refactor Header UI and navigation states (#201)

* (SP: 3) [Frontend] Refactor Header UI and navigation states

- Add icon to the language switcher

- Add GitHub icon with stars indicator (frontend only)

- Update logo styles

- Improve touch interaction styles

- Verify correct placement and alignment of all header components

- Make mobile header modal full-screen

- Disable background scroll when mobile menu is open

- Highlight active navigation item

- Update navigation styles:

- Highlight Shop link when user is on Home pages
- Highlight Home link when user is on Shop pages
- Style changes only, no routing or logic changes

* fix CodeRabbit

* update HeaderButton styles

* fix: add accessibility for HeaderButton

* (SP: 3) [Testing] Vitest config + unit + integration tests for quiz module (#204)

* 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(leaderboard): improve table mobile

* fix(leaderboard): correct malformed shadow class syntax for avatar glow

* Feature/leaderboard style update (#206)

* fix:leaderboard  update leaderboard-style

* fix:leaderboard update leaderboard-style on mobile

* fix: resolve CodeRabbit issues and conflicts

* fix: move row border to first cell to resolve CodeRabbit issue

* fix: move row border to first cell to resolve CodeRabbit issue new

* fix(leaderboard): improve table mobile

* fix(leaderboard): correct malformed shadow class syntax for avatar glow

* test(q&a): add comprehensive qa tests and coverage setup (#208)

* test(q&a): add comprehensive qa tests and coverage setup

* test(q&a): align mocks and reset in qa tests

* (SP: 1) [Frontend] Remove Contacts References (#211)

* test(q&a): add comprehensive qa tests and coverage setup

* test(q&a): align mocks and reset in qa tests

* chore(nav): remove contacts page references

* Sanity (#209)

* 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

* chore(release): update changelog for v0.5.0

* chore(release): v0.5.0

* [Refactor] Code Quality Improvements: Accessibility, Mobile Support, … (#213)

* fix(leaderboard): adjust podium heights for better visibility on desktop

* Feature/leaderboard style update (#214)

* fix(leaderboard): fix layout centering

* feat(Blog) (#216)

* feat(Blog) (#218)

* 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

* (SP: 1) feat(i18n): translate 404 error page (#217)

- Add 404 translations (uk/en/pl)
- Implement [Global/Local/Combined] strategy
- Add helpful navigation links

* (SP: 2) [Frontend] Refactor Home HeroSection and Footer stylestor/home (#221)

* (SP:1) fix: 404 page layout (#219)

- 404 translations (uk/en/pl)
- Implement Global strategy

* feat(Blog) (#222)

* 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

* Update AI model from 'llama-3.3-70b-versatile' to 'llama3-70b-8192' (#223)

* (SP 2) [Frontend] Update Features section content and improve mobile UX (#224)

* (SP 2) [Frontend] Update Features section content and improve mobile UX

- Features Section: Refined feature content and visuals.
- Mobile UX: Improved responsive layout and scaling for feature cards and interactive elements.
- Visual Enhancements: Added dynamic particle background effects to the Pricing section.

* fix(review): address accessibility, security, and performance feedback

* fix(review): resolve accessibility and hydration issues

* fix(perf): implement frame-rate independent animations

* fix(review): address accessibility, security, and performance feedback

* fix(review): enable SSR for features section and support HiDPI canvas

* fix(review): correct HiDPI logic for particle canvas measurements

* (SP:3) feat(i18n): add UA and PL translations for shop/admin pages

Add comprehensive i18n support for shop and admin sections in 3 languages (en, uk,
  pl).

  Translation coverage:
  - Shop pages: main page, products, cart, checkout, orders
  - Admin pages: dashboard, products management, orders management
  - Navigation: header, mobile menu, category links
  - Product components: cards, filters, sort, badges (NEW/SALE)
  - Category names: Apparel, Lifestyle, Collectibles
  - All UI buttons, labels, and actions

  Key changes:
  - Added ~250+ translation keys to messages/en.json, messages/uk.json,
  messages/pl.json
  - Updated 20+ components to use useTranslations() and getTranslations()
  - Implemented color translation in cart and product detail pages
  - Translated hero message
  - Added badge translations

* fix(i18n): correct translation keys and localization in shop pages

  - Replace confusing error.order with success.orderLabel in checkout success page
  heading
  - Localize boolean stockRestored display (yes/no instead of true/false) in order
  details
  - Fix active state detection for shop category links in mobile menu using search
  params
  - Add missing translation keys (orderLabel, yes, no) to all locales (en, uk, pl)

* fix(netlify): resolve AI API crash and 404 locale/theme issues

AI fixes:
  - Extract getClientIp to separate file (avoid db import crash)
  - Add missing zod dependency to package.json

  404 page fixes:
  - Use NEXT_LOCALE cookie for locale detection on Netlify
  - Add theme detection script in root layout
  - Update styling with hero background and gradient text

* Update frontend/app/not-found.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* (SP:3) feat(i18n): translate about page and auth form validation messages

  - Add about page translations (EN, UK, PL)
  - Add auth.fields.validation translations for form errors

* fix(api): resolve Netlify 503 errors and harden AI explain endpoint

 - Use dynamic import for groq-sdk (Netlify compatibility)                                                    - Bypass rate limiting for unknown IPs (serverless safety)
  - Safe JSON parsing with request.text() + empty body check
  - Fix ReferenceError: remove undefined errorMessage variable
  - Remove sensitive debug info from client responses
  - Add i18n keys: pricing.heading, sponsors.ctaAriaLabel

* feat(api): add GET health check endpoint for ai-explain

* chore(release): v0.5.1

---------

Co-authored-by: liudmylasovetovs <milkaegik@gmail.com>
Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com>
Co-authored-by: Anna <komrakova.anna@gmail.com>
Co-authored-by: AlinaRyabova <alinavr7@gmail.com>
Co-authored-by: Yevhenii Datsenko <yevheniydatsenko@gmail.com>
Co-authored-by: YNazymko12 <yulychka12@gmail.com>
Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@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: Yuliia Nazymko <122815071+YNazymko12@users.noreply.github.com>
Co-authored-by: Yevhenii Datsenko <134847096+yevheniidatsenko@users.noreply.github.com>
Co-authored-by: tetiana zorii <tanyusha.zoriy@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@ViktorSvertoka ViktorSvertoka mentioned this pull request Jan 31, 2026
20 tasks
ViktorSvertoka added a commit that referenced this pull request Jan 31, 2026
* (SP: 1) [Security] Enforce origin posture for shop APIs (admin/checkout same-origin; internal/webhooks non-browser) + docs

* (SP: 1) [DB] Align stripe_events.order_id FK CASCADE across schema and migrations

* feat(i18n): localize quiz anti-cheat, header and blog filters (#175)

* feat(Blog): Adding last published post to the blog and category page, recommended posts, Changing styles to one unified format, Bug fixes

* Update leaderboard-style

* Update leaderboard-style

* teat(Blog): fix of hover on author, fix of the line

* (SP: 3) [Observability] Extend structured logging + correlation IDs across all shop routes; purge console.*; enforce explicit error codes

* (SP: 1) [Admin][Security] Add safe product delete (PRODUCT_IN_USE) + mobile cards UI; tighten env/docs, locale normalization, cache-control, and logging semantics

* fix: npm installing

* (SP: 1) [Admin] Align products list in use checks with DB column names (order_items/inventory_moves)

* fix:Update leaderboard: fixed background

* fix: remove email from CurrentUser type to prevent PII exposure

* refactor: align leaderboard UI with brand style (fixed bg, css vars, podium glow)

* (SP: 1) [Frontend] About Us Page. Fixed game, topics, mobile layout

- Fixed mobile tabs in FeaturesSection (icon-only on mobile)
- Fixed game bugs: collision detection, animation, scoring system
- Added multiple obstacle types with level progression
- Improved game sizing for mobile while preserving desktop
- Updated TopicsSection with local SVG icons and hover borders
- Made DynamicGridBackground static grid opt-in via showStaticGrid prop
- Limited SponsorsWall to display max 10 sponsors
- Optimized CommunitySection button layout for mobile

* refactor: update accent color hover effects to Footer

- Update Footer links to use --accent-primary on hover
- Update ThemeToggle icons to use --accent-primary on hover
- Both components adapt colors to light/dark theme

* refactor: improve accessibility

- Add focus-visible styles for keyboard navigation accessibility

* (SP: 1) [Shop] Fix Stripe checkout success redirect (remove duplicate locale /uk/uk) (#186)

* fix:leaderboard  update leaderboard-style

* fix:leaderboard  update leaderboard-style (#187)

* fix:leaderboard update leaderboard-style on mobile

* fix: resolve CodeRabbit issues and conflicts

* fix:leaderboard update leaderboard-style on mobile (#188)

* fix:leaderboard  update leaderboard-style

* fix:leaderboard update leaderboard-style on mobile

* fix: resolve CodeRabbit issues and conflicts

---------



* (SP: 1) [Frontend] Changing hero headline on shop main page (#190)

* (SP: 1) [Shop] Fix checkout redirect 404 by removing duplicate locale in in-app routes and Stripe return_url

* (SP: 1) [Shop] Fix locale cart page and orderid page

* (SP: 1) [Frontend] Changin hero headline on shop main page

* (SP: 1) [Frontend] Fix styles shop home page, buttons (#191)

* fix: move row border to first cell to resolve CodeRabbit issue

* fix: move row border to first cell to resolve CodeRabbit issue new

* Feature/leaderboard style update (#192)

* (SP: 7) [UI] Quiz UI polish: tabs styling, category accents, color scheme (#181, #193, #194) (#195)

* Sanity (#196)

* 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

* (SP: 3) [AI] Add AI word helper with Groq integration (#200)

* (SP: 3) [AI] Add AI word helper with Groq integration

- Implement Groq API with Llama 3.1 70B model
- Add text selection detection on Q&A page
- Create floating "Explain" button
- Build draggable modal with 3-language support (uk/en/pl)
- Add localStorage caching for instant repeated lookups
- Implement guest CTA (login/signup)
- Add rate limiting (10 requests/min)
- Auth-gated feature (registered users only)

Components:
- SelectableText: Detects text selection
- FloatingExplainButton: Appears on selection
- AIWordHelper: Main modal with explanations

* (SP: 1) i18n: fix Polish locale and set EN as default

* Sanity (#202)

* 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

* Sanity (#203)

* 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

* (SP: 3) [Frontend] Refactor Header UI and navigation states (#201)

* (SP: 3) [Frontend] Refactor Header UI and navigation states

- Add icon to the language switcher

- Add GitHub icon with stars indicator (frontend only)

- Update logo styles

- Improve touch interaction styles

- Verify correct placement and alignment of all header components

- Make mobile header modal full-screen

- Disable background scroll when mobile menu is open

- Highlight active navigation item

- Update navigation styles:

- Highlight Shop link when user is on Home pages
- Highlight Home link when user is on Shop pages
- Style changes only, no routing or logic changes

* fix CodeRabbit

* update HeaderButton styles

* fix: add accessibility for HeaderButton

* (SP: 3) [Testing] Vitest config + unit + integration tests for quiz module (#204)

* 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(leaderboard): improve table mobile

* fix(leaderboard): correct malformed shadow class syntax for avatar glow

* Feature/leaderboard style update (#206)

* fix:leaderboard  update leaderboard-style

* fix:leaderboard update leaderboard-style on mobile

* fix: resolve CodeRabbit issues and conflicts

* fix: move row border to first cell to resolve CodeRabbit issue

* fix: move row border to first cell to resolve CodeRabbit issue new

* fix(leaderboard): improve table mobile

* fix(leaderboard): correct malformed shadow class syntax for avatar glow

* test(q&a): add comprehensive qa tests and coverage setup (#208)

* test(q&a): add comprehensive qa tests and coverage setup

* test(q&a): align mocks and reset in qa tests

* (SP: 1) [Frontend] Remove Contacts References (#211)

* test(q&a): add comprehensive qa tests and coverage setup

* test(q&a): align mocks and reset in qa tests

* chore(nav): remove contacts page references

* Sanity (#209)

* 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

* chore(release): update changelog for v0.5.0

* chore(release): v0.5.0

* [Refactor] Code Quality Improvements: Accessibility, Mobile Support, … (#213)

* fix(leaderboard): adjust podium heights for better visibility on desktop

* Feature/leaderboard style update (#214)

* fix(leaderboard): fix layout centering

* feat(Blog) (#216)

* feat(Blog) (#218)

* 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

* (SP: 1) feat(i18n): translate 404 error page (#217)

- Add 404 translations (uk/en/pl)
- Implement [Global/Local/Combined] strategy
- Add helpful navigation links

* (SP: 2) [Frontend] Refactor Home HeroSection and Footer stylestor/home (#221)

* (SP:1) fix: 404 page layout (#219)

- 404 translations (uk/en/pl)
- Implement Global strategy

* feat(Blog) (#222)

* 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

* Update AI model from 'llama-3.3-70b-versatile' to 'llama3-70b-8192' (#223)

* (SP 2) [Frontend] Update Features section content and improve mobile UX (#224)

* (SP 2) [Frontend] Update Features section content and improve mobile UX

- Features Section: Refined feature content and visuals.
- Mobile UX: Improved responsive layout and scaling for feature cards and interactive elements.
- Visual Enhancements: Added dynamic particle background effects to the Pricing section.

* fix(review): address accessibility, security, and performance feedback

* fix(review): resolve accessibility and hydration issues

* fix(perf): implement frame-rate independent animations

* fix(review): address accessibility, security, and performance feedback

* fix(review): enable SSR for features section and support HiDPI canvas

* fix(review): correct HiDPI logic for particle canvas measurements

* (SP:3) feat(i18n): add UA and PL translations for shop/admin pages

Add comprehensive i18n support for shop and admin sections in 3 languages (en, uk,
  pl).

  Translation coverage:
  - Shop pages: main page, products, cart, checkout, orders
  - Admin pages: dashboard, products management, orders management
  - Navigation: header, mobile menu, category links
  - Product components: cards, filters, sort, badges (NEW/SALE)
  - Category names: Apparel, Lifestyle, Collectibles
  - All UI buttons, labels, and actions

  Key changes:
  - Added ~250+ translation keys to messages/en.json, messages/uk.json,
  messages/pl.json
  - Updated 20+ components to use useTranslations() and getTranslations()
  - Implemented color translation in cart and product detail pages
  - Translated hero message
  - Added badge translations

* fix(i18n): correct translation keys and localization in shop pages

  - Replace confusing error.order with success.orderLabel in checkout success page
  heading
  - Localize boolean stockRestored display (yes/no instead of true/false) in order
  details
  - Fix active state detection for shop category links in mobile menu using search
  params
  - Add missing translation keys (orderLabel, yes, no) to all locales (en, uk, pl)

* fix(netlify): resolve AI API crash and 404 locale/theme issues

AI fixes:
  - Extract getClientIp to separate file (avoid db import crash)
  - Add missing zod dependency to package.json

  404 page fixes:
  - Use NEXT_LOCALE cookie for locale detection on Netlify
  - Add theme detection script in root layout
  - Update styling with hero background and gradient text

* Update frontend/app/not-found.tsx



* (SP:3) feat(i18n): translate about page and auth form validation messages

  - Add about page translations (EN, UK, PL)
  - Add auth.fields.validation translations for form errors

* fix(api): resolve Netlify 503 errors and harden AI explain endpoint

 - Use dynamic import for groq-sdk (Netlify compatibility)                                                    - Bypass rate limiting for unknown IPs (serverless safety)
  - Safe JSON parsing with request.text() + empty body check
  - Fix ReferenceError: remove undefined errorMessage variable
  - Remove sensitive debug info from client responses
  - Add i18n keys: pricing.heading, sponsors.ctaAriaLabel

* feat(api): add GET health check endpoint for ai-explain

* chore(release): v0.5.1

---------

Co-authored-by: liudmylasovetovs <milkaegik@gmail.com>
Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com>
Co-authored-by: Anna <komrakova.anna@gmail.com>
Co-authored-by: AlinaRyabova <alinavr7@gmail.com>
Co-authored-by: Yevhenii Datsenko <yevheniydatsenko@gmail.com>
Co-authored-by: YNazymko12 <yulychka12@gmail.com>
Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@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: Yuliia Nazymko <122815071+YNazymko12@users.noreply.github.com>
Co-authored-by: Yevhenii Datsenko <134847096+yevheniidatsenko@users.noreply.github.com>
Co-authored-by: tetiana zorii <tanyusha.zoriy@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@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