From 1f55ba2d56acb46c4b72db1e52e592cb90ebf937 Mon Sep 17 00:00:00 2001 From: kuekhaoyang Date: Mon, 17 Nov 2025 16:34:13 +0800 Subject: [PATCH] feat: Add Popular Features component and integrate with search functionality; enhance SearchForm with clear button and initial query handling; update scrollbar styling utility --- app/api/douban/recommend/route.ts | 34 +++ app/globals.css | 10 + app/page.tsx | 91 ++++---- components/home/PopularFeatures.tsx | 319 ++++++++++++++++++++++++++++ components/search/SearchForm.tsx | 30 ++- components/ui/Icon.tsx | 16 ++ lib/hooks/useParallelSearch.ts | 2 +- next.config.ts | 21 +- 8 files changed, 470 insertions(+), 53 deletions(-) create mode 100644 app/api/douban/recommend/route.ts create mode 100644 components/home/PopularFeatures.tsx diff --git a/app/api/douban/recommend/route.ts b/app/api/douban/recommend/route.ts new file mode 100644 index 0000000..4d864ac --- /dev/null +++ b/app/api/douban/recommend/route.ts @@ -0,0 +1,34 @@ +import { NextResponse } from 'next/server'; + +export async function GET(request: Request) { + const { searchParams } = new URL(request.url); + const tag = searchParams.get('tag') || '热门'; + const pageLimit = searchParams.get('page_limit') || '20'; + const pageStart = searchParams.get('page_start') || '0'; + const type = searchParams.get('type') || 'movie'; // movie or tv + + try { + const url = `https://movie.douban.com/j/search_subjects?type=${type}&tag=${encodeURIComponent(tag)}&sort=recommend&page_limit=${pageLimit}&page_start=${pageStart}`; + + const response = await fetch(url, { + headers: { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36', + 'Referer': 'https://movie.douban.com/', + }, + next: { revalidate: 3600 }, // Cache for 1 hour + }); + + if (!response.ok) { + throw new Error(`Douban API returned ${response.status}`); + } + + const data = await response.json(); + return NextResponse.json(data); + } catch (error) { + console.error('Douban API error:', error); + return NextResponse.json( + { subjects: [], error: 'Failed to fetch recommendations' }, + { status: 500 } + ); + } +} diff --git a/app/globals.css b/app/globals.css index f35f65a..7b6106e 100644 --- a/app/globals.css +++ b/app/globals.css @@ -103,6 +103,16 @@ body.dark, background-clip: padding-box; } +/* Hide scrollbar utility */ +.scrollbar-hide { + -ms-overflow-style: none; + scrollbar-width: none; +} + +.scrollbar-hide::-webkit-scrollbar { + display: none; +} + /* Custom animations */ @keyframes fade-in { from { diff --git a/app/page.tsx b/app/page.tsx index 25cad77..e439b65 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -11,6 +11,7 @@ import { EmptyState } from '@/components/search/EmptyState'; import { NoResults } from '@/components/search/NoResults'; import { ResultsHeader } from '@/components/search/ResultsHeader'; import { TypeBadges } from '@/components/search/TypeBadges'; +import { PopularFeatures } from '@/components/home/PopularFeatures'; import { useSearchCache } from '@/lib/hooks/useSearchCache'; import { useParallelSearch } from '@/lib/hooks/useParallelSearch'; import { useTypeBadges } from '@/lib/hooks/useTypeBadges'; @@ -85,57 +86,53 @@ function HomePage() { return (
{/* Glass Navbar */} -