209 lines
5.9 KiB
TypeScript
209 lines
5.9 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import Image from "next/image";
|
|
import Link from "next/link";
|
|
import { listDataRegional } from "@/service/landing/landing";
|
|
import {
|
|
Carousel,
|
|
CarouselContent,
|
|
CarouselItem,
|
|
CarouselNext,
|
|
CarouselPrevious,
|
|
} from "@/components/ui/carousel";
|
|
|
|
interface ContentItem {
|
|
id: number;
|
|
slug: string;
|
|
title: string;
|
|
thumbnailLink?: string;
|
|
categoryName?: string;
|
|
}
|
|
|
|
interface RegionOrSatker {
|
|
name: string;
|
|
slug: string;
|
|
logo: string;
|
|
}
|
|
|
|
interface AllContentPageProps {
|
|
typeId: string; // 1 = image, 2 = video, 3 = text, 4 = audio
|
|
title: string;
|
|
basePath: "image" | "video" | "document" | "audio";
|
|
mode: "polda" | "satker";
|
|
dataList: RegionOrSatker[];
|
|
}
|
|
|
|
export default function AllContentPage({
|
|
typeId,
|
|
title,
|
|
basePath,
|
|
mode,
|
|
dataList,
|
|
}: AllContentPageProps) {
|
|
const [contents, setContents] = useState<Record<string, ContentItem[]>>({});
|
|
|
|
useEffect(() => {
|
|
async function fetchData() {
|
|
const promises = dataList.map(async (region) => {
|
|
try {
|
|
const res = await listDataRegional(
|
|
typeId,
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
10,
|
|
0,
|
|
"createdAt"
|
|
);
|
|
return { slug: region.slug, data: res?.data?.data?.content || [] };
|
|
} catch {
|
|
return { slug: region.slug, data: [] };
|
|
}
|
|
});
|
|
|
|
const resultsArray = await Promise.all(promises);
|
|
const results: Record<string, ContentItem[]> = {};
|
|
resultsArray.forEach((r) => {
|
|
results[r.slug] = r.data;
|
|
});
|
|
setContents(results);
|
|
}
|
|
|
|
fetchData();
|
|
}, [typeId, dataList]);
|
|
|
|
function renderCard(item: ContentItem, regionSlug: string) {
|
|
const href = `/${mode}/${regionSlug}/${basePath}/detail/${item.slug}`;
|
|
|
|
if (basePath === "image" || basePath === "video") {
|
|
return (
|
|
<Link
|
|
href={href}
|
|
className="block border rounded-md overflow-hidden hover:shadow-md transition"
|
|
>
|
|
{item.thumbnailLink && (
|
|
<Image
|
|
src={item.thumbnailLink}
|
|
alt={item.title}
|
|
width={400}
|
|
height={250}
|
|
className="w-full h-40 object-cover"
|
|
/>
|
|
)}
|
|
<div className="p-2 text-sm font-medium truncate">{item.title}</div>
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
if (basePath === "document") {
|
|
return (
|
|
<Link
|
|
href={href}
|
|
className="cursor-pointer rounded-lg shadow-md overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 block"
|
|
>
|
|
<div className="bg-[#e0c350] flex items-center justify-center h-[170px] text-white">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="80"
|
|
height="80"
|
|
viewBox="0 0 16 16"
|
|
>
|
|
<path
|
|
fill="currentColor"
|
|
d="M5 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V5.4a1.5 1.5 0 0 0-.44-1.06L9.6 1.4A1.5 1.5 0 0 0 8.6 1z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<div className="p-4">
|
|
<div className="text-[12px] font-bold text-red-600 uppercase">
|
|
{item.categoryName?.toUpperCase() ?? "Document"}
|
|
</div>
|
|
<div className="font-semibold text-gray-900 dark:text-white text-xl leading-snug line-clamp-3">
|
|
{item.title}
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
if (basePath === "audio") {
|
|
return (
|
|
<Link
|
|
href={href}
|
|
className="cursor-pointer bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition overflow-hidden block"
|
|
>
|
|
<div className="flex items-center justify-center bg-[#bb3523] w-full h-[170px] text-white">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="80"
|
|
height="80"
|
|
viewBox="0 0 20 20"
|
|
>
|
|
<path
|
|
fill="currentColor"
|
|
d="M14.7 2.2A1 1 0 0 1 16 3.2v6L8 11v6.5a2.5 2.5 0 1 1-1-2V5.4a1 1 0 0 1 .7-1z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<div className="p-4">
|
|
<p className="text-[12px] font-bold text-[#bb3523] uppercase mb-1">
|
|
{item.categoryName?.toUpperCase() ?? "Audio"}
|
|
</p>
|
|
<p className="text-xl font-semibold text-black dark:text-white line-clamp-3">
|
|
{item.title}
|
|
</p>
|
|
</div>
|
|
</Link>
|
|
);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="max-w-7xl mx-auto px-4 py-8">
|
|
<h1 className="text-2xl font-bold mb-6">{title}</h1>
|
|
|
|
{dataList.map((region) => (
|
|
<div key={region.slug} className="mb-12">
|
|
{/* Header */}
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<Image
|
|
src={region.logo}
|
|
alt={region.name}
|
|
width={40}
|
|
height={40}
|
|
className="rounded-full"
|
|
/>
|
|
<h2 className="text-lg font-semibold">{region.name}</h2>
|
|
</div>
|
|
|
|
{/* Carousel Konten */}
|
|
{contents[region.slug]?.length > 0 ? (
|
|
<Carousel className="w-full">
|
|
<CarouselContent>
|
|
{contents[region.slug].map((item) => (
|
|
<CarouselItem
|
|
key={item.id}
|
|
className="basis-2/3 md:basis-1/3 lg:basis-1/4"
|
|
>
|
|
{renderCard(item, region.slug)}
|
|
</CarouselItem>
|
|
))}
|
|
</CarouselContent>
|
|
<CarouselPrevious />
|
|
<CarouselNext />
|
|
</Carousel>
|
|
) : (
|
|
<p className="text-gray-500">Tidak ada konten di {region.name}</p>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|