Skip to content

Commit eb46ed1

Browse files
ViktorSvertokaliudmylasovetovsTiZoriiKomrakovaAnnaAlinaRyabova
authored
Release v0.5.1 (#229)
* (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>
1 parent a1562c4 commit eb46ed1

93 files changed

Lines changed: 5213 additions & 1519 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
209209
- Improved accessibility and visual consistency across components
210210
- Resolved locale duplication in Stripe checkout redirects
211211
- Cleaned up redundant UI states, placeholders, and legacy styles
212+
213+
## [0.5.1] - 2026-01-31
214+
215+
### Added
216+
217+
- Enhanced About page experience:
218+
- Refreshed Features and Pricing sections with clearer messaging
219+
- Interactive particle-based backgrounds with reduced-motion support
220+
- New reusable UI components: `ParticleCanvas`, `GradientBadge`,
221+
`SectionHeading`
222+
- Improved mobile responsiveness and layout stability
223+
- Blog improvements:
224+
- Dynamic grid backgrounds across blog pages
225+
- Featured post CTA in blog hero
226+
- Author filtering via URL with adaptive header behavior
227+
- Improved 404 error pages:
228+
- Fully localized (uk / en / pl)
229+
- Unified global rendering strategy
230+
- Clear navigation actions back to Home
231+
- AI Word Helper updates:
232+
- Switched model to `llama3-70b-8192` for improved response quality
233+
- Accessibility & UX:
234+
- Better keyboard navigation for highlighted terms
235+
- Improved touch and mobile interaction handling
236+
237+
### Changed
238+
239+
- Home page refinements:
240+
- Hero section refactored into smaller reusable components
241+
- Updated color palette, spacing, animations, and mobile behavior
242+
- Footer styling updated to match refreshed brand visuals
243+
- Blog layout aligned with updated design language and spacing rules
244+
- Default locale updated from `uk` to `en` with safer type validation
245+
- Internal codebase cleanup:
246+
- Improved i18n defaults and validation
247+
- Better cache initialization and error handling
248+
249+
### Fixed
250+
251+
- Fixed blog post image rendering for latest posts
252+
- Resolved layout centering issues on Leaderboard
253+
- Improved stability of text selection detection for AI helper
254+
- Fixed social icon hover styles in dark mode
255+
- Reduced visual overlap issues on small mobile screens

frontend/app/[locale]/about/page.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getTranslations } from "next-intl/server"
12
import { getPlatformStats } from "@/lib/about/stats"
23
import { getSponsors } from "@/lib/about/github-sponsors"
34

@@ -7,6 +8,14 @@ import { FeaturesSection } from "@/components/about/FeaturesSection"
78
import { PricingSection } from "@/components/about/PricingSection"
89
import { CommunitySection } from "@/components/about/CommunitySection"
910

11+
export async function generateMetadata() {
12+
const t = await getTranslations("about")
13+
return {
14+
title: t("metaTitle"),
15+
description: t("metaDescription"),
16+
}
17+
}
18+
1019
export default async function AboutPage() {
1120
const [stats, sponsors] = await Promise.all([
1221
getPlatformStats(),
@@ -17,13 +26,13 @@ export default async function AboutPage() {
1726
<main className="min-h-screen bg-gray-50 dark:bg-black overflow-hidden text-gray-900 dark:text-white
1827
w-[100vw] relative left-[50%] right-[50%] -ml-[50vw] -mr-[50vw]"
1928
>
20-
29+
2130
<HeroSection stats={stats} />
2231
<TopicsSection />
2332
<FeaturesSection />
2433
<PricingSection sponsors={sponsors} />
2534
<CommunitySection />
26-
35+
2736
</main>
2837
)
2938
}

frontend/app/[locale]/blog/[slug]/PostDetails.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { getTranslations } from 'next-intl/server';
55
import { client } from '@/client';
66
import { Link } from '@/i18n/routing';
77
import { formatBlogDate } from '@/lib/blog/date';
8+
import { DynamicGridBackground } from '@/components/shared/DynamicGridBackground';
89

910
export const revalidate = 0;
1011

@@ -289,7 +290,8 @@ export default async function PostDetails({
289290
: null;
290291

291292
return (
292-
<main className="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
293+
<DynamicGridBackground className="bg-gray-50 transition-colors duration-300 dark:bg-transparent py-10">
294+
<main className="relative z-10 mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
293295
{breadcrumbsJsonLd && (
294296
<script
295297
type="application/ld+json"
@@ -501,7 +503,8 @@ export default async function PostDetails({
501503
{post.resourceLink && null}
502504

503505
{(authorBio || authorName || authorMeta) && null}
504-
</main>
506+
</main>
507+
</DynamicGridBackground>
505508
);
506509
}
507510

frontend/app/[locale]/blog/category/[category]/page.tsx

Lines changed: 82 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { client } from '@/client';
66
import { Link } from '@/i18n/routing';
77
import { BlogCategoryGrid } from '@/components/blog/BlogCategoryGrid';
88
import { formatBlogDate } from '@/lib/blog/date';
9+
import { DynamicGridBackground } from '@/components/shared/DynamicGridBackground';
10+
import { FeaturedPostCtaButton } from '@/components/blog/FeaturedPostCtaButton';
911

1012
export const revalidate = 0;
1113

@@ -85,89 +87,89 @@ export default async function BlogCategoryPage({
8587
const featuredDate = formatBlogDate(featuredPost?.publishedAt);
8688

8789
return (
88-
<main className="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
89-
<nav className="mb-6" aria-label="Breadcrumb">
90-
<ol className="flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
91-
<li className="flex items-center gap-2">
92-
<Link
93-
href="/blog"
94-
className="transition hover:text-[var(--accent-primary)] hover:underline underline-offset-4"
95-
>
96-
{tNav('blog')}
97-
</Link>
98-
<span>&gt;</span>
99-
</li>
100-
<li className="flex items-center gap-2">
101-
<span className="text-[var(--accent-primary)]" aria-current="page">
102-
{categoryDisplay}
103-
</span>
104-
</li>
105-
</ol>
106-
</nav>
107-
<h1 className="text-4xl font-bold mb-4 text-center">
108-
{categoryDisplay}
109-
</h1>
110-
{featuredPost?.mainImage && (
111-
<section className="mt-10">
112-
<article className="group relative overflow-hidden rounded-3xl bg-white dark:bg-black">
113-
<div className="h-[320px] w-full overflow-hidden sm:h-[380px] md:h-[450px] lg:h-[618px] max-h-[65vh]">
114-
<Image
115-
src={featuredPost.mainImage}
116-
alt={featuredPost.title}
117-
width={1400}
118-
height={800}
119-
className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-[1.03]"
120-
priority={false}
121-
/>
122-
</div>
123-
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-56 bg-gradient-to-t from-white/95 via-white/70 to-transparent dark:from-black/90 dark:via-black/60 sm:h-64" />
124-
<div className="absolute inset-x-0 bottom-0 p-6 sm:p-8">
125-
{featuredPost.categories?.[0] && (
126-
<div className="text-sm font-medium text-gray-900 dark:text-gray-100">
127-
{featuredPost.categories[0]}
128-
</div>
129-
)}
130-
<h2 className="mt-2 text-3xl font-semibold text-gray-900 transition group-hover:text-[var(--accent-primary)] dark:text-white dark:group-hover:text-[var(--accent-primary)] sm:text-4xl">
131-
{featuredPost.title}
132-
</h2>
133-
<div className="mt-3 flex items-center gap-3 text-sm text-gray-800 dark:text-gray-200">
134-
{featuredPost.author?.image && (
135-
<Image
136-
src={featuredPost.author.image}
137-
alt={featuredPost.author.name || 'Author'}
138-
width={28}
139-
height={28}
140-
className="h-7 w-7 rounded-full object-cover"
141-
/>
142-
)}
143-
{featuredPost.author?.name && (
144-
<span>{featuredPost.author.name}</span>
145-
)}
146-
{featuredPost.author?.name && featuredDate && <span>·</span>}
147-
{featuredDate && featuredPost.publishedAt && (
148-
<time dateTime={featuredPost.publishedAt}>
149-
{featuredDate}
150-
</time>
151-
)}
152-
</div>
90+
<DynamicGridBackground className="bg-gray-50 transition-colors duration-300 dark:bg-transparent py-10">
91+
<main className="relative z-10 mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
92+
<nav className="mb-6" aria-label="Breadcrumb">
93+
<ol className="flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
94+
<li className="flex items-center gap-2">
15395
<Link
154-
href={`/blog/${featuredPost.slug.current}`}
155-
className="absolute bottom-6 right-6 inline-flex h-11 w-11 items-center justify-center rounded-full bg-[var(--accent-primary)] text-white opacity-0 transition group-hover:opacity-100 hover:brightness-110"
156-
aria-label={featuredPost.title}
96+
href="/blog"
97+
className="transition hover:text-[var(--accent-primary)] hover:underline underline-offset-4"
15798
>
158-
<span aria-hidden="true"></span>
99+
{tNav('blog')}
159100
</Link>
160-
</div>
161-
</article>
162-
</section>
163-
)}
164-
<div className="mt-12">
165-
<BlogCategoryGrid posts={restPosts} />
166-
</div>
167-
{!posts.length && (
168-
<p className="text-center text-gray-500 mt-10">{t('noPosts')}</p>
169-
)}
170-
</main>
101+
<span>&gt;</span>
102+
</li>
103+
<li className="flex items-center gap-2">
104+
<span className="text-[var(--accent-primary)]" aria-current="page">
105+
{categoryDisplay}
106+
</span>
107+
</li>
108+
</ol>
109+
</nav>
110+
<h1 className="text-4xl font-bold mb-4 text-left">
111+
{categoryDisplay}
112+
</h1>
113+
{featuredPost?.mainImage && (
114+
<section className="mt-10">
115+
<article className="group relative overflow-hidden rounded-3xl bg-white dark:bg-black">
116+
<div className="h-[320px] w-full overflow-hidden sm:h-[380px] md:h-[450px] lg:h-[618px] max-h-[65vh]">
117+
<Image
118+
src={featuredPost.mainImage}
119+
alt={featuredPost.title}
120+
width={1400}
121+
height={800}
122+
className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-[1.03]"
123+
priority={false}
124+
/>
125+
</div>
126+
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-56 bg-gradient-to-t from-white/95 via-white/70 to-transparent dark:from-black/90 dark:via-black/60 sm:h-64" />
127+
<div className="absolute inset-x-0 bottom-0 p-6 sm:p-8">
128+
{featuredPost.categories?.[0] && (
129+
<div className="text-sm font-medium text-gray-900 dark:text-gray-100">
130+
{featuredPost.categories[0]}
131+
</div>
132+
)}
133+
<h2 className="mt-2 text-3xl font-semibold text-gray-900 transition group-hover:text-[var(--accent-primary)] dark:text-white dark:group-hover:text-[var(--accent-primary)] sm:text-4xl">
134+
{featuredPost.title}
135+
</h2>
136+
<div className="mt-3 flex items-center gap-3 text-sm text-gray-800 dark:text-gray-200">
137+
{featuredPost.author?.image && (
138+
<Image
139+
src={featuredPost.author.image}
140+
alt={featuredPost.author.name || 'Author'}
141+
width={28}
142+
height={28}
143+
className="h-7 w-7 rounded-full object-cover"
144+
/>
145+
)}
146+
{featuredPost.author?.name && (
147+
<span>{featuredPost.author.name}</span>
148+
)}
149+
{featuredPost.author?.name && featuredDate && <span>·</span>}
150+
{featuredDate && featuredPost.publishedAt && (
151+
<time dateTime={featuredPost.publishedAt}>
152+
{featuredDate}
153+
</time>
154+
)}
155+
</div>
156+
</div>
157+
<FeaturedPostCtaButton
158+
href={`/blog/${featuredPost.slug.current}`}
159+
label={featuredPost.title || 'Read more'}
160+
className="!absolute !bottom-6 !right-6 z-10 h-11 w-11 rounded-full bg-[var(--accent-primary)] text-white opacity-0 shadow-sm transition group-hover:opacity-100 focus-visible:opacity-100 group-focus-within:opacity-100"
161+
/>
162+
</article>
163+
</section>
164+
)}
165+
<div className="mt-12">
166+
<BlogCategoryGrid posts={restPosts} />
167+
</div>
168+
{!posts.length && (
169+
<p className="text-center text-gray-500 mt-10">{t('noPosts')}</p>
170+
)}
171+
</main>
172+
</DynamicGridBackground>
171173
);
172174
}
173175

frontend/app/[locale]/blog/page.tsx

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { unstable_noStore as noStore } from 'next/cache';
33
import { getTranslations } from 'next-intl/server';
44
import { client } from '@/client';
55
import BlogFilters from '@/components/blog/BlogFilters';
6+
import { BlogPageHeader } from '@/components/blog/BlogPageHeader';
7+
import { DynamicGridBackground } from '@/components/shared/DynamicGridBackground';
68

79
export const revalidate = 0;
810

@@ -22,12 +24,18 @@ export async function generateMetadata({
2224

2325
export default async function BlogPage({
2426
params,
27+
searchParams,
2528
}: {
2629
params: Promise<{ locale: string }>;
30+
searchParams?: Promise<{ [key: string]: string | string[] | undefined }>;
2731
}) {
2832
noStore();
2933
const { locale } = await params;
3034
const t = await getTranslations({ locale, namespace: 'blog' });
35+
const sp = searchParams ? await searchParams : undefined;
36+
const authorParam =
37+
typeof sp?.author === 'string' ? sp.author.trim() : '';
38+
const hasAuthorFilter = authorParam.length > 0;
3139

3240
const posts = await client.withConfig({ useCdn: false }).fetch(
3341
groq`
@@ -77,16 +85,17 @@ export default async function BlogPage({
7785
const featuredPost = posts?.[0];
7886

7987
return (
80-
<main className="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
81-
<h1 className="text-4xl font-bold mb-4 text-center">{t('title')}</h1>
82-
<p className="mx-auto max-w-2xl text-center text-base text-gray-500 dark:text-gray-400">
83-
{t('subtitle')}
84-
</p>
85-
<BlogFilters
86-
posts={posts}
87-
categories={categories}
88-
featuredPost={featuredPost}
89-
/>
90-
</main>
88+
<DynamicGridBackground className="bg-gray-50 transition-colors duration-300 dark:bg-transparent py-10">
89+
<main className="relative z-10 mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
90+
{!hasAuthorFilter && (
91+
<BlogPageHeader title={t('title')} subtitle={t('subtitle')} />
92+
)}
93+
<BlogFilters
94+
posts={posts}
95+
categories={categories}
96+
featuredPost={featuredPost}
97+
/>
98+
</main>
99+
</DynamicGridBackground>
91100
);
92101
}

frontend/app/[locale]/not-found.tsx

Lines changed: 0 additions & 8 deletions
This file was deleted.

frontend/app/[locale]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { getTranslations } from 'next-intl/server';
2-
import HeroSection from '@/components/shared/HeroSection';
2+
import HeroSection from '@/components/home/HeroSection';
33

44
export async function generateMetadata({
55
params,

frontend/app/[locale]/shop/admin/orders/[id]/RefundButton.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { useRouter } from 'next/navigation';
44
import { useId, useState, useTransition } from 'react';
5+
import { useTranslations } from 'next-intl';
56

67
type Props = {
78
orderId: string;
@@ -10,6 +11,7 @@ type Props = {
1011

1112
export function RefundButton({ orderId, disabled }: Props) {
1213
const router = useRouter();
14+
const t = useTranslations('shop.admin.refund');
1315
const [isPending, startTransition] = useTransition();
1416
const [error, setError] = useState<string | null>(null);
1517
const errorId = useId();
@@ -59,13 +61,9 @@ export function RefundButton({ orderId, disabled }: Props) {
5961
aria-busy={isPending}
6062
aria-describedby={error ? errorId : undefined}
6163
className="rounded-md border border-border px-3 py-1.5 text-sm font-medium text-foreground transition-colors hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-50"
62-
title={
63-
disabled
64-
? 'Refund is only available for paid Stripe orders'
65-
: undefined
66-
}
64+
title={disabled ? t('onlyForPaid') : undefined}
6765
>
68-
{isPending ? 'Refunding…' : 'Refund'}
66+
{isPending ? t('refunding') : t('refund')}
6967
</button>
7068

7169
{error ? (

0 commit comments

Comments
 (0)