From fa7dcc2b081653b93ef22c0e90efaefdf0e76c02 Mon Sep 17 00:00:00 2001 From: echo Date: Sat, 28 Feb 2026 18:47:11 +0100 Subject: [PATCH] feat: add general category, fix header wrapping, show last 5 live blog updates --- backend/src/modules/strapi.service.ts | 1 + .../article/content-types/article/schema.json | 4 +- .../home/PinnedLiveBlogsSidebar.tsx | 104 +++++++++++++++++- frontend/src/components/layout/Header.tsx | 2 +- 4 files changed, 107 insertions(+), 4 deletions(-) diff --git a/backend/src/modules/strapi.service.ts b/backend/src/modules/strapi.service.ts index f823bdd..ce40944 100644 --- a/backend/src/modules/strapi.service.ts +++ b/backend/src/modules/strapi.service.ts @@ -131,6 +131,7 @@ export class StrapiService { // Map CMS category slugs to Macedonian display names const categoryMap: Record = { + general: { name: 'Општо', description: 'Општи вести и теми' }, sport: { name: 'Спорт', description: 'Спортски вести и анализи' }, art: { name: 'Уметност', description: 'Уметност, култура и забава' }, science: { name: 'Наука', description: 'Научни откритија и технологија' }, diff --git a/cms/cms/src/api/article/content-types/article/schema.json b/cms/cms/src/api/article/content-types/article/schema.json index d387c37..a90b185 100644 --- a/cms/cms/src/api/article/content-types/article/schema.json +++ b/cms/cms/src/api/article/content-types/article/schema.json @@ -65,8 +65,8 @@ }, "category": { "type": "enumeration", - "enum": ["sport", "art", "science"], - "default": "sport", + "enum": ["general", "sport", "art", "science"], + "default": "general", "required": true } } diff --git a/frontend/src/components/home/PinnedLiveBlogsSidebar.tsx b/frontend/src/components/home/PinnedLiveBlogsSidebar.tsx index bd6f74d..77b8a17 100644 --- a/frontend/src/components/home/PinnedLiveBlogsSidebar.tsx +++ b/frontend/src/components/home/PinnedLiveBlogsSidebar.tsx @@ -2,9 +2,12 @@ import { useQuery } from '@tanstack/react-query'; import { Link } from '@tanstack/react-router'; import { fetchPinnedLiveBlogs } from '@/lib/api'; import { Button } from '@/components/ui/button'; -import { Calendar, Eye, MessageSquare, Pin } from 'lucide-react'; +import { Calendar, Eye, MessageSquare, Pin, ChevronDown, ChevronUp, Clock } from 'lucide-react'; +import { useState } from 'react'; export function PinnedLiveBlogsSidebar() { + const [showUpdates, setShowUpdates] = useState(false); + const { data: liveBlogs, isLoading, error } = useQuery({ queryKey: ['pinned-live-blogs'], queryFn: fetchPinnedLiveBlogs, @@ -47,6 +50,52 @@ export function PinnedLiveBlogsSidebar() { }); }; + const formatRelativeTime = (dateString: string) => { + const date = new Date(dateString); + const now = new Date(); + const diffMs = now.getTime() - date.getTime(); + const diffMins = Math.floor(diffMs / 60000); + const diffHours = Math.floor(diffMs / 3600000); + const diffDays = Math.floor(diffMs / 86400000); + + if (diffMins < 1) return 'сега'; + if (diffMins < 60) return `${diffMins}м`; + if (diffHours < 24) return `${diffHours}ч`; + return `${diffDays}д`; + }; + + // Collect last 5 updates from all pinned live blogs + const getLastFiveUpdates = () => { + if (!liveBlogs) return []; + + const allUpdates: Array<{ + id: string; + content: string; + createdAt: string; + liveBlogTitle: string; + liveBlogSlug: string; + }> = []; + + liveBlogs.forEach((liveBlog) => { + if (liveBlog.updates && liveBlog.updates.length > 0) { + liveBlog.updates.forEach((update) => { + allUpdates.push({ + ...update, + liveBlogTitle: liveBlog.title, + liveBlogSlug: liveBlog.slug, + }); + }); + } + }); + + // Sort by date descending and take first 5 + return allUpdates + .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) + .slice(0, 5); + }; + + const lastFiveUpdates = getLastFiveUpdates(); + if (isLoading) { return (
@@ -102,6 +151,59 @@ export function PinnedLiveBlogsSidebar() { return (
+ {/* Latest Updates Section - Collapsible */} + {lastFiveUpdates.length > 0 && ( +
+ + + {showUpdates && ( +
+ {lastFiveUpdates.map((update) => ( + +
+
+ + {update.liveBlogTitle} + + + {formatRelativeTime(update.createdAt)} + +
+

+ {update.content.replace(/<[^>]*>/g, '').substring(0, 120)} + {update.content.length > 120 ? '...' : ''} +

+
+ + ))} +
+ )} +
+ )} +
diff --git a/frontend/src/components/layout/Header.tsx b/frontend/src/components/layout/Header.tsx index 826a3c0..a5e92c5 100644 --- a/frontend/src/components/layout/Header.tsx +++ b/frontend/src/components/layout/Header.tsx @@ -58,7 +58,7 @@ export function Header() {
-

+

P l a