188 lines
5.9 KiB
TypeScript
188 lines
5.9 KiB
TypeScript
"use client";
|
|
|
|
import { tiktokHumasData } from "@/services/generate-article";
|
|
import {
|
|
Button,
|
|
Card,
|
|
CardBody,
|
|
CardFooter,
|
|
Image,
|
|
Spinner,
|
|
} from "@heroui/react";
|
|
import Link from "next/link";
|
|
import { useEffect, useState } from "react";
|
|
import { Swiper, SwiperSlide } from "swiper/react";
|
|
import "swiper/css";
|
|
import "swiper/css/navigation";
|
|
import "swiper/css/pagination";
|
|
import { Navigation, Pagination } from "swiper/modules";
|
|
import dayjs from "dayjs";
|
|
import relativeTime from "dayjs/plugin/relativeTime";
|
|
import { PlayIcon, TiktokLandingIcon } from "@/components/icons";
|
|
import { textEllipsis } from "@/utils/global";
|
|
|
|
const getRelativeTime = (timestamp: number): string => {
|
|
const now = Date.now();
|
|
const timeDiff = now - timestamp * 1000; // Konversi ke milidetik
|
|
|
|
const seconds = Math.floor(timeDiff / 1000);
|
|
const minutes = Math.floor(seconds / 60);
|
|
const hours = Math.floor(minutes / 60);
|
|
const days = Math.floor(hours / 24);
|
|
const weeks = Math.floor(days / 7);
|
|
const months = Math.floor(days / 30);
|
|
const years = Math.floor(days / 365);
|
|
|
|
if (seconds < 60) return "just now";
|
|
if (minutes < 60) return `${minutes} min ago`;
|
|
if (hours < 24) return `${hours} hour${hours > 1 ? "s" : ""} ago`;
|
|
if (days < 7) return `${days} day${days > 1 ? "s" : ""} ago`;
|
|
if (weeks < 4) return `${weeks} week${weeks > 1 ? "s" : ""} ago`;
|
|
if (months < 12) return `${months} month${months > 1 ? "s" : ""} ago`;
|
|
return `${years} year${years > 1 ? "s" : ""} ago`;
|
|
};
|
|
export default function TiktokWidget() {
|
|
const [tiktokData, setTiktokData] = useState<any>([]);
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, []);
|
|
|
|
const fetchData = async () => {
|
|
const res = await tiktokHumasData();
|
|
setTiktokData(res?.data?.data);
|
|
};
|
|
|
|
const [isVideoLoaded, setIsVideoLoaded] = useState(0);
|
|
const videoUrl = "https://www.tiktok.com/@divhumaspolriofficial/video/";
|
|
|
|
const loadTikTokVideo = (id: number) => {
|
|
setIsVideoLoaded(id);
|
|
// Tambahkan script TikTok embed setelah video dimuat
|
|
const script = document.createElement("script");
|
|
script.src = "https://www.tiktok.com/embed.js";
|
|
script.async = true;
|
|
document.body.appendChild(script);
|
|
};
|
|
|
|
const tiktokPlayer = (data: any) => {
|
|
return (
|
|
<div>
|
|
{isVideoLoaded !== data.id ? (
|
|
<a
|
|
onClick={() => loadTikTokVideo(data.id)}
|
|
className="relative flex flex-col gap-2 justify-center items-center lg:py-10 px-5 transition-all duration-300 hover:bg-black/10 h-[756px] active:bg-black/20"
|
|
>
|
|
<TiktokLandingIcon size={30} />
|
|
<p>{textEllipsis(data.desc, 200)}</p>
|
|
<div className="flex flex-col gap-1">
|
|
<p className="font-bold">Divisi Humas Polri</p>
|
|
<p className="text-xs">{getRelativeTime(data.create_time)}</p>
|
|
</div>
|
|
|
|
<Image
|
|
src="/divhumas.png"
|
|
alt="humas-polri"
|
|
className="!w-[48px]"
|
|
/>
|
|
|
|
<div
|
|
className="absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-100 transition-opacity duration-300"
|
|
onClick={(e) => {
|
|
e.stopPropagation(); // Mencegah masalah klik tertangkap oleh elemen lain
|
|
loadTikTokVideo(data.id);
|
|
}}
|
|
>
|
|
<button className="bg-black/50 text-white rounded-full p-3">
|
|
<PlayIcon />
|
|
</button>
|
|
</div>
|
|
</a>
|
|
) : (
|
|
<blockquote
|
|
className="tiktok-embed !my-0"
|
|
cite={videoUrl + String(data.id)}
|
|
data-video-id={data.id}
|
|
style={{ minWidth: "325px" }}
|
|
>
|
|
<section></section>
|
|
</blockquote>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
return tiktokData?.length > 1 ? (
|
|
<div className="flex flex-col gap-4">
|
|
<div className="flex justify-between w-full px-2 items-center">
|
|
<div className="flex flex-row gap-2 items-center">
|
|
<Image src="/divhumas.png" alt="humas-polri" className="!w-[68px]" />{" "}
|
|
<p className="font-semibold">Divisi Humas Polri</p>
|
|
</div>
|
|
<Link
|
|
target="_blank"
|
|
href="https://www.tiktok.com/@divhumaspolriofficial"
|
|
>
|
|
<Button radius="sm" color="primary">
|
|
Follow us
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
<Swiper
|
|
navigation={true}
|
|
modules={[Navigation]}
|
|
spaceBetween={10}
|
|
slidesPerView={1}
|
|
breakpoints={{
|
|
// When the window width is less than 640px
|
|
720: {
|
|
slidesPerView: 3, // Set slidesPerView to 1 on mobile
|
|
},
|
|
1080: {
|
|
slidesPerView: 4,
|
|
},
|
|
}}
|
|
pagination={true}
|
|
className="mySwiper custom-button-slider !px-[8px]"
|
|
onSwiper={(swiper) => {
|
|
swiper.navigation.nextEl?.classList.add(
|
|
"bg-white",
|
|
"!text-black",
|
|
"rounded-full",
|
|
"!w-[40px]",
|
|
"!h-[40px]",
|
|
"!border-2"
|
|
);
|
|
swiper.navigation.prevEl?.classList.add(
|
|
"bg-white",
|
|
"!text-black",
|
|
"rounded-full",
|
|
"!w-[40px]",
|
|
"!h-[40px]",
|
|
"!border-2"
|
|
);
|
|
}}
|
|
>
|
|
{tiktokData?.map((data: any) => (
|
|
<SwiperSlide
|
|
key={data.id}
|
|
className="hover:shadow-xl hover:opacity-90"
|
|
>
|
|
<Card
|
|
isPressable
|
|
shadow="none"
|
|
className=" bg-white text-black border-2 w-full"
|
|
>
|
|
<CardBody className="!p-0 overflow-visible text-center flex flex-col justify-center items-center text-sm">
|
|
{tiktokPlayer(data)}
|
|
</CardBody>
|
|
</Card>
|
|
</SwiperSlide>
|
|
))}
|
|
</Swiper>
|
|
</div>
|
|
) : (
|
|
<div className="w-full flex justify-center items-center">
|
|
<Spinner size="lg" className="mx-auto" color="default" />
|
|
</div>
|
|
);
|
|
}
|