From 8a0768e16c01ce38bff197d7d655c581952ab3e3 Mon Sep 17 00:00:00 2001 From: Umar faruk Date: Wed, 27 May 2026 23:58:27 +0000 Subject: [PATCH] feat: implement Topic Feed UI/UX enhancement - Add Topic and TopicPost types to socialUtils - Add useTopicFeed hook with pagination, sort, and infinite scroll - Add TopicFeed component with skeleton, empty, and error states - Add /topics/[slug] page with metadata generation --- src/app/topics/[slug]/page.tsx | 27 ++++ src/components/social/TopicFeed.tsx | 216 ++++++++++++++++++++++++++++ src/hooks/useTopicFeed.ts | 90 ++++++++++++ src/utils/socialUtils.ts | 21 +++ 4 files changed, 354 insertions(+) create mode 100644 src/app/topics/[slug]/page.tsx create mode 100644 src/components/social/TopicFeed.tsx create mode 100644 src/hooks/useTopicFeed.ts diff --git a/src/app/topics/[slug]/page.tsx b/src/app/topics/[slug]/page.tsx new file mode 100644 index 00000000..a9936548 --- /dev/null +++ b/src/app/topics/[slug]/page.tsx @@ -0,0 +1,27 @@ +import type { Metadata } from 'next'; +import TopicFeed from '@/components/social/TopicFeed'; + +interface TopicPageProps { + params: Promise<{ slug: string }>; +} + +export async function generateMetadata({ params }: TopicPageProps): Promise { + const { slug } = await params; + const name = slug.replace(/-/g, ' '); + return { + title: `#${name} · TeachLink`, + description: `Explore posts and discussions about ${name} on TeachLink.`, + }; +} + +export default async function TopicPage({ params }: TopicPageProps) { + const { slug } = await params; + + return ( +
+
+ +
+
+ ); +} diff --git a/src/components/social/TopicFeed.tsx b/src/components/social/TopicFeed.tsx new file mode 100644 index 00000000..81c06cd8 --- /dev/null +++ b/src/components/social/TopicFeed.tsx @@ -0,0 +1,216 @@ +'use client'; + +import { useEffect, useRef } from 'react'; +import Image from 'next/image'; +import { UserCircle, Heart, MessageCircle, TrendingUp, Clock, ArrowUp } from 'lucide-react'; +import { useTopicFeed, type SortOption } from '@/hooks/useTopicFeed'; +import { getRelativeTime, formatFollowerCount } from '@/utils/socialUtils'; + +// ─── Skeleton ───────────────────────────────────────────────────────────────── + +function PostSkeleton() { + return ( +