Files
cineprime/app/page.tsx
2026-01-31 17:21:32 +08:00

137 lines
4.6 KiB
TypeScript

import HeroSlider from '@/components/HeroSlider';
import MovieRow from '@/components/MovieRow';
import { getHomepageData, getMovieDetail, HomeSection, Subject } from '@/lib/api';
import { getDracinHome, getDracinDetail, DramaboxItem } from '@/lib/dramabox';
export default async function Home() {
console.log("Fetching homepage data...");
let data;
let dracinData: DramaboxItem[] = [];
try {
// Fetch both datasets in parallel
const [homeData, dracinRes] = await Promise.all([
getHomepageData(),
getDracinHome(1, 10) // Fetch top 10 Dracin items
]);
data = homeData;
dracinData = dracinRes;
} catch (e) {
console.error("Error generating homepage:", e);
return (
<div className="pt-32 text-center text-red-500 px-4">
<h2 className="text-xl font-bold mb-2">Error loading data</h2>
<p className="text-sm font-mono bg-black/50 p-4 rounded inline-block max-w-full overflow-auto">
{e instanceof Error ? e.message : String(e)}
</p>
</div>
);
}
// Use operatingList if available, otherwise fallback to homeList
let contentList = data.operatingList || data.homeList;
if (!contentList) {
contentList = [];
}
// Map Dracin Data to Subject format
if (dracinData.length > 0) {
const dracinSection: HomeSection = {
type: 'SUBJECTS_MOVIE', // Reuse existing type for rendering
title: 'Latest Dracin', // Title for the new row
subjects: dracinData.map(d => ({
subjectId: d.id.toString(),
subjectType: 3, // Custom type
title: d.name,
description: d.introduction,
releaseDate: "",
genre: d.tags.join(", "),
cover: { url: d.cover, width: 300, height: 450 },
image: { url: d.cover, width: 300, height: 450 },
countryName: "China",
imdbRatingValue: "N/A",
detailPath: "",
isDracin: true
}))
};
// Insert Dracin section after the first movie section (usually index 1)
if (contentList.length > 1) {
contentList.splice(1, 0, dracinSection);
} else {
contentList.push(dracinSection);
}
}
if (contentList.length === 0) {
return <div className="pt-32 text-white text-center">No Content Available</div>;
}
// Find Banner section
const bannerSection = contentList.find((s) => s.type === 'BANNER');
// Get all items for the slider
let bannerItems = bannerSection?.banner?.items || bannerSection?.subjects || [];
// Enrich banner items with descriptions if missing
if (bannerItems.length > 0) {
bannerItems = await Promise.all(bannerItems.map(async (item: any) => {
const hasDesc = item.description && item.description !== "No description available.";
const hasSubjectDesc = item.subject?.description && item.subject.description !== "No description available.";
if (hasDesc || hasSubjectDesc) return item;
const id = item.subjectId || item.id || item.subject?.subjectId;
if (!id) return item;
try {
// Try fetching as a movie first (most common and covers the long numeric IDs we saw)
try {
const detail = await getMovieDetail(id);
if (detail && detail.subject && detail.subject.description) {
return { ...item, description: detail.subject.description };
}
} catch (movieError) {
// Ignore error and try Dracin
}
// If movie fetch failed or didn't return a description, try Dracin
const { drama } = await getDracinDetail(id);
if (drama && drama.introduction) {
return { ...item, description: drama.introduction };
}
} catch (e) {
// Log as warning to differentiate from critical errors
// console.warn(`Failed to enrich banner item ${id}:`, e instanceof Error ? e.message : e);
}
return item;
}));
}
return (
<main className="relative pb-16">
{/* Hero Section */}
{bannerItems.length > 0 && <HeroSlider items={bannerItems} />}
{/* Movie Rows */}
<div className="flex flex-col gap-2 -mt-16 md:-mt-32 relative z-10 pl-0 md:pl-0">
{contentList.map((section, index) => {
if (section.type === 'SUBJECTS_MOVIE' && section.subjects && section.subjects.length > 0) {
const isDracinSection = section.title === 'Latest Dracin';
return (
<MovieRow
key={`${section.title}-${index}`}
title={section.title}
movies={section.subjects}
headerContent={undefined}
/>
);
}
return null;
})}
</div>
</main>
);
}