kontenhumas-fe/components/main/content/video-detail.tsx

337 lines
11 KiB
TypeScript

"use client";
import Image from "next/image";
import { Calendar, Clock, Eye } from "lucide-react";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { useState, useEffect } from "react";
import {
FaFacebookF,
FaTiktok,
FaYoutube,
FaWhatsapp,
FaInstagram,
FaTwitter,
FaCheck,
FaLink,
FaShareAlt,
} from "react-icons/fa";
import { getDetail, getArticleDetail } from "@/service/landing/landing";
import VideoPlayer from "@/utils/video-player";
export default function VideoDetail({ id }: { id: number }) {
const [copied, setCopied] = useState(false);
const [showShareMenu, setShowShareMenu] = useState(false);
const [data, setData] = useState<any>(null);
const [loading, setLoading] = useState(true);
const [selectedVideo, setSelectedVideo] = useState(0);
const handleCopyLink = async () => {
try {
await navigator.clipboard.writeText(window.location.href);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch (err) {
console.error("Failed to copy: ", err);
}
};
const SocialItem = ({
icon,
label,
}: {
icon: React.ReactNode;
label: string;
}) => (
<div className="flex items-center gap-3 cursor-pointer hover:opacity-80">
<div className="bg-[#C6A455] p-2 rounded-full text-white">{icon}</div>
<span className="text-sm">{label}</span>
</div>
);
useEffect(() => {
const fetchDetail = async () => {
try {
setLoading(true);
// Try new Articles API first
const response = await getArticleDetail(id);
console.log("Article Detail API response:", response);
// if (response?.error) {
// console.error("Articles API failed, falling back to old API");
// // Fallback to old API
// const fallbackResponse = await getDetail(id);
// setData(fallbackResponse?.data?.data);
// return;
// }
// Handle new API response structure
const articleData = response?.data?.data;
if (articleData) {
// Transform article data to match old structure for backward compatibility
const transformedData = {
id: articleData.id,
title: articleData.title,
description: articleData.description,
createdAt: articleData.createdAt,
clickCount: articleData.viewCount,
creatorGroupLevelName: articleData.createdByName || "Unknown",
uploadedBy: {
publisher: articleData.createdByName || "MABES POLRI",
},
files:
articleData.files?.map((file: any) => ({
id: file.id,
url: file.file_url,
fileName: file.file_name,
filePath: file.file_path,
fileThumbnail: file.file_thumbnail,
fileAlt: file.file_alt,
widthPixel: file.width_pixel,
heightPixel: file.height_pixel,
size: file.size,
downloadCount: file.download_count,
createdAt: file.created_at,
updatedAt: file.updated_at,
thumbnailFileUrl:
file.file_thumbnail || articleData.thumbnailUrl,
...file,
})) || [],
...articleData,
};
setData(transformedData);
}
} catch (error) {
console.error("Error fetching detail:", error);
// Try fallback to old API if new API fails
try {
// const fallbackResponse = await getDetail(id);
// setData(fallbackResponse?.data?.data);
} catch (fallbackError) {
console.error("Fallback API also failed:", fallbackError);
}
} finally {
setLoading(false);
}
};
if (id) fetchDetail();
}, [id]);
if (loading) {
return (
<div className="max-w-6xl mx-auto px-4 py-6">
<p>Loading...</p>
</div>
);
}
if (!data) {
return (
<div className="max-w-6xl mx-auto px-4 py-6">
<p>Data tidak ditemukan</p>
</div>
);
}
return (
<div className="max-w-6xl mx-auto px-4 py-6 space-y-6">
{/* Bagian Video Utama */}
<div className="relative max-h-screen overflow-hidden">
<div className="w-full max-h-screen aspect-video">
<div className="w-full h-full object-contain">
<VideoPlayer
url={
// data?.files?.[selectedVideo]?.secondaryUrl?.trim()
// ? data.files[selectedVideo].secondaryUrl
// : data?.files?.[selectedVideo]?.fileUrl?.includes("viewer/")
// ? `${process.env.NEXT_PUBLIC_API}/media/view?id=${data.files[selectedVideo].id}&operation=file&type=video`
// : data?.files?.[selectedVideo]?.fileUrl?.trim()
// ?
data.files[selectedVideo].fileUrl
// : "/notfound.mp4"
}
/>
</div>
</div>
<div className="absolute top-4 left-4"></div>
</div>
{/* Thumbnail bawah */}
<div className="py-2 flex flex-row gap-3 flex-wrap">
{data?.files?.map((file: any, index: number) => (
<div
key={file?.id}
onClick={() => setSelectedVideo(index)}
className="cursor-pointer flex flex-col items-center gap-1"
>
<Image
src={
file?.thumbnailFileUrl?.trim()
? file.thumbnailFileUrl
: "/notfound.png"
}
alt={file?.fileName || "thumbnail"}
width={160}
height={90}
className={`w-32 h-20 object-cover rounded-md hover:ring-2 ${
selectedVideo === index ? "ring-2 ring-red-600" : ""
}`}
/>
</div>
))}
</div>
<div className="flex flex-col md:flex-row md:items-center md:justify-between text-sm text-muted-foreground">
<div className="flex flex-wrap items-center gap-2">
<span className="font-semibold text-black border-r-2 pr-2 border-black">
by {data?.uploadedBy?.publisher || "MABES POLRI"}
</span>
<span className="flex items-center gap-1 text-black">
<Calendar className="w-4 h-4" />
{new Date(data.createdAt)
.toLocaleString("id-ID", {
day: "2-digit",
month: "short",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
hour12: false,
timeZone: "Asia/Jakarta",
})
.replace(".", ":")}{" "}
WIB
</span>
{/* <span className="flex items-center gap-1 border-r-2 pr-2 border-black text-black">
<Clock className="w-4 h-4" />
{data.time || "-"}
</span> */}
<span className="flex items-center gap-1 border-r-2 pr-2 border-black text-black">
<Eye className="w-4 h-4" />
{data.clickCount || 0}
</span>
<span className="text-black">
{" "}
Creator: {data.creatorGroupLevelName}
</span>
</div>
</div>
<div className="flex flex-col md:flex-row gap-6 mt-6">
{/* Sidebar actions */}
{/* <div className="hidden md:flex flex-col gap-4 relative z-10">
<div className="flex gap-2 items-center">
<Button
onClick={handleCopyLink}
size="lg"
className="justify-start bg-black text-white rounded-full"
>
{copied ? <FaCheck /> : <FaLink />}
</Button>
<span>COPY LINK</span>
</div>
<div className="flex gap-2 items-center relative">
<Button
onClick={() => setShowShareMenu(!showShareMenu)}
size="lg"
className="justify-start bg-[#C6A455] text-white rounded-full"
>
<FaShareAlt />
</Button>
<span>SHARE</span>
{showShareMenu && (
<div className="absolute left-16 top-0 bg-white p-4 rounded-lg shadow-lg flex flex-col gap-3 w-48">
<SocialItem icon={<FaFacebookF />} label="Facebook" />
<SocialItem icon={<FaTiktok />} label="TikTok" />
<SocialItem icon={<FaYoutube />} label="YouTube" />
<SocialItem icon={<FaWhatsapp />} label="WhatsApp" />
<SocialItem icon={<FaInstagram />} label="Instagram" />
<SocialItem icon={<FaTwitter />} label="Twitter" />
</div>
)}
</div>
<div className="flex gap-2 items-center">
<Link href={`/content/video/comment/${id}`}>
<Button
variant="default"
size="lg"
className="justify-start bg-[#FFAD10] rounded-full mr-2 text-white"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="15"
height="15"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M10 3h4a8 8 0 1 1 0 16v3.5c-5-2-12-5-12-11.5a8 8 0 0 1 8-8"
/>
</svg>
</Button>
COMMENT
</Link>
</div>
</div> */}
{/* Content */}
<div className="flex-1 space-y-4">
<h1 className="text-xl font-bold">{data.title}</h1>
<div className="text-base text-gray-700 leading-relaxed space-y-3">
<p>{data.description}</p>
</div>
{/* Actions bawah */}
<div className="flex flex-wrap md:flex-row justify-center gap-4 my-20">
<div className="flex gap-2 items-center">
<Button
onClick={handleCopyLink}
size="lg"
className="justify-start bg-black text-white rounded-full"
>
{copied ? <FaCheck /> : <FaLink />}
</Button>
<span>COPY LINK</span>
</div>
<div className="flex gap-2 items-center">
<Button
onClick={() => setShowShareMenu(!showShareMenu)}
size="lg"
className="justify-start bg-[#C6A455] text-white rounded-full"
>
<FaShareAlt />
</Button>
<span>SHARE</span>
</div>
<div className="flex gap-2 items-center">
<Link href={`/content/video/comment/${id}`}>
<Button
variant="default"
size="lg"
className="justify-start bg-[#FFAD10] rounded-full mr-2 text-white"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="15"
height="15"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M10 3h4a8 8 0 1 1 0 16v3.5c-5-2-12-5-12-11.5a8 8 0 0 1 8-8"
/>
</svg>
</Button>
COMMENT
</Link>
</div>
</div>
</div>
</div>
</div>
);
}