'use client'; import { useState, useEffect, useRef } from 'react'; import { Search as SearchIcon } from 'lucide-react'; import { getSearch, Subject } from '@/lib/api'; import { searchDracinAction } from './actions'; import { DramaboxItem } from '@/lib/dramabox'; import MovieCard from '@/components/MovieCard'; export default function SearchPage() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(false); const [searchType, setSearchType] = useState<'movie' | 'dracin'>('movie'); const abortControllerRef = useRef(null); const performSearch = async (searchQuery: string, pageNum: number, append: boolean = false, typeOverride?: 'movie' | 'dracin') => { const currentType = typeOverride || searchType; // Cancel previous request if (abortControllerRef.current) { abortControllerRef.current.abort(); } const controller = new AbortController(); abortControllerRef.current = controller; setLoading(true); if (!append) setResults([]); try { let movieList: Subject[] = []; let dracinList: Subject[] = []; let moviesHasMore = false; let dracinHasMore = false; if (currentType === 'movie') { const moviesData = await getSearch(searchQuery, pageNum, controller.signal); if (controller.signal.aborted) return; movieList = Array.isArray(moviesData) ? moviesData : ((moviesData as any).items || (moviesData as any).list || (moviesData as any).subjects || (moviesData as any).searchList || []); moviesHasMore = (moviesData as any).pager?.hasMore || false; } else { const dracinData = await searchDracinAction(searchQuery, pageNum); if (controller.signal.aborted) return; dracinList = (dracinData as DramaboxItem[]).map(item => ({ subjectId: item.id.toString(), title: item.name, cover: { url: item.cover, width: 0, height: 0 }, image: { url: item.cover, width: 0, height: 0 }, rate: 'N/A', isDracin: true, subjectType: 0, description: item.introduction || '', releaseDate: '', genre: item.tags ? item.tags.join(', ') : '', originalTitle: item.name, viewCount: item.playCount || 0, rec: false, countryName: 'CN', imdbRatingValue: 'N/A', detailPath: `/dracin/${item.id}` })); dracinHasMore = Array.isArray(dracinData) && dracinData.length >= 20; } // Unified list (though now they are separate, deduplication is still good practice) const combined = [...movieList, ...dracinList]; const uniqueList = Array.from(new Map(combined.map((item: Subject) => [item.subjectId, item])).values()) as Subject[]; if (append) { setResults(prev => { const newCombined = [...prev, ...uniqueList]; return Array.from(new Map(newCombined.map((item: Subject) => [item.subjectId, item])).values()) as Subject[]; }); } else { setResults(uniqueList); } setHasMore(currentType === 'movie' ? moviesHasMore : dracinHasMore); } catch (error: any) { if (error.name === 'AbortError') return; console.error(error); } finally { if (!controller.signal.aborted) { setLoading(false); } } }; useEffect(() => { const delayDebounceFn = setTimeout(() => { if (query.trim()) { setPage(1); performSearch(query, 1, false, searchType); } else { setResults([]); setHasMore(false); if (abortControllerRef.current) { abortControllerRef.current.abort(); } } }, 800); return () => { clearTimeout(delayDebounceFn); }; }, [query, searchType]); const handleTypeChange = (type: 'movie' | 'dracin') => { if (type === searchType) return; setSearchType(type); setPage(1); setResults([]); setHasMore(false); if (query.trim()) { performSearch(query, 1, false, type); } }; const handleLoadMore = () => { const nextPage = page + 1; setPage(nextPage); performSearch(query, nextPage, true); }; return (
{/* Fixed Search Type & Input Header */}
{/* Search Type Selector */}
setQuery(e.target.value)} placeholder={`Search ${searchType === 'movie' ? 'movies' : 'dramas'}...`} className="w-full bg-[#1f1f1f] border border-gray-700 text-white px-12 py-3 rounded-full text-lg focus:outline-none focus:border-red-600 transition-colors shadow-lg" autoFocus />
{/* Results Content - Padded to start below fixed headers */}
{loading && page === 1 && (
Searching {searchType === 'movie' ? 'Movies' : 'Dramas'}...
)}
{results.map((item) => ( ))}
{!loading && hasMore && results.length > 0 && query && (
)} {loading && page > 1 && (
Loading more {searchType === 'movie' ? 'movies' : 'dramas'}...
)} {!loading && query && results.length === 0 && (
🔍

No results found

We couldn't find any {searchType === 'movie' ? 'movies' : 'dramas'} matching "{query}".

Try adjusting your search or switching categories.

)}
); }