feat: related content and featured cross-content sidebar widgets

- Add excludeId arg to videos and articles GraphQL resolvers
- Add excludeId + featured params to getVideos/getArticles services
- Video page: fetch related videos by tag + featured article in parallel
- Article page: fetch related articles by category + featured video in parallel
- Implement sidebar widgets with thumbnails, metadata, hover interactions
- Add videos.related and magazine.related i18n keys
- Seed dummy articles (spotlight, interview, psychology) and videos with
  overlapping tags for testing related content

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 18:35:04 +01:00
parent 6d1726ee97
commit 91951667e3
8 changed files with 251 additions and 85 deletions

View File

@@ -245,6 +245,7 @@ const ARTICLES_QUERY = gql`
$limit: Int
$featured: Boolean
$tag: String
$excludeId: String
) {
articles(
search: $search
@@ -254,6 +255,7 @@ const ARTICLES_QUERY = gql`
limit: $limit
featured: $featured
tag: $tag
excludeId: $excludeId
) {
items {
id
@@ -287,6 +289,7 @@ export async function getArticles(
limit?: number;
featured?: boolean;
tag?: string;
excludeId?: string;
} = {},
fetchFn?: typeof globalThis.fetch,
): Promise<{ items: Article[]; total: number }> {
@@ -366,6 +369,7 @@ const VIDEOS_QUERY = gql`
$sortBy: String
$duration: String
$tag: String
$excludeId: String
) {
videos(
modelId: $modelId
@@ -376,6 +380,7 @@ const VIDEOS_QUERY = gql`
sortBy: $sortBy
duration: $duration
tag: $tag
excludeId: $excludeId
) {
items {
id
@@ -416,6 +421,8 @@ export async function getVideos(
offset?: number;
limit?: number;
tag?: string;
featured?: boolean;
excludeId?: string;
} = {},
fetchFn?: typeof globalThis.fetch,
): Promise<{ items: Video[]; total: number }> {