mediahub-fe/app/[locale]/(public)/indeks/detail/[slug]/page.tsx

377 lines
18 KiB
TypeScript

"use client";
import { Textarea } from "@/components/ui/textarea";
import { useParams, usePathname, useSearchParams } from "next/navigation";
import React, { useEffect, useState } from "react";
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel";
import { Link, useRouter } from "@/i18n/routing";
import { deleteBlogComments, getBlogComments, getDetailIndeks, getPublicSuggestionList, postBlogComments, publicDetailBlog } from "@/service/landing/landing";
import { formatDateToIndonesian } from "@/utils/globals";
import { Icon } from "@iconify/react/dist/iconify.js";
import { getCookiesDecrypt } from "@/lib/utils";
import { close, loading } from "@/config/swal";
import { Input } from "@/components/ui/input";
import { useTranslations } from "next-intl";
import Image from "next/image";
const IndeksDetail = () => {
const searchParams = useSearchParams();
const id = searchParams?.get("id");
const [indeksData, setIndeksData] = useState<any>();
const params = useParams();
const slug = params?.slug;
const [indexData, setIndexData] = useState<any>();
const [message, setMessage] = useState("");
const [messageChild, setMessageChild] = useState("");
const userId = getCookiesDecrypt("uie");
const userRoleId = getCookiesDecrypt("urie");
const router: any = useRouter();
const [listComments, setListComments] = useState([]);
const t = useTranslations("LandingPage");
useEffect(() => {
initFetch();
detailFetch();
}, []);
const initFetch = async () => {
const response = await getDetailIndeks();
console.log(response);
setIndexData(response?.data?.data?.content);
};
const detailFetch = async () => {
const response = await publicDetailBlog(slug);
console.log(response);
setIndeksData(response?.data?.data);
getDataComment(response?.data?.data?.id);
};
async function getDataComment(id?: any) {
const response = await getBlogComments(id || indeksData?.id);
console.log(response.data?.data);
setListComments(response.data?.data);
}
const showInput = (e: any) => {
console.log(document.querySelector(`#${e}`)?.classList);
document.querySelector(`#${e}`)?.classList.toggle("hidden");
};
async function sendCommentParent() {
if (message?.length > 3) {
loading();
const data = {
blogId: indeksData?.id,
message: message,
parentId: null,
};
const response = await postBlogComments(data);
console.log(response);
setMessage("");
getDataComment();
close();
}
}
// async function sendCommentChild(parentId: any) {
// if (messageChild.length > 3) {
// loading();
// const data = {
// blogId: indeksData?.id,
// message: messageChild,
// parentId,
// };
// console.log(data);
// const response = await postBlogComments(data);
// console.log(response);
// const responseGet = await getPublicSuggestionList(slug);
// console.log(responseGet.data?.data);
// setMessageChild("");
// // $(":input").val("");
// close();
// }
// }
async function sendCommentChild(parentId: any) {
const inputMsg = document.querySelector(`#input-comment-${parentId}`) as HTMLInputElement;
if (inputMsg && inputMsg.value.length > 3) {
loading();
const data = {
blogId: indeksData?.id,
message: inputMsg.value,
parentId,
};
console.log(data);
const response = await postBlogComments(data);
console.log(response);
const responseGet = await getPublicSuggestionList(slug);
console.log(responseGet.data?.data);
getDataComment();
inputMsg.value = "";
close();
}
}
async function deleteDataComment(dataId: any) {
loading();
const response = await deleteBlogComments(dataId);
console.log(response);
getDataComment();
close();
}
const getInputValue = (e: any) => {
const message = e.target.value;
console.log(message);
setMessage(message);
getDataComment();
};
const postData = () => {
if (Number(userRoleId) < 1) {
router.push("/auth");
} else {
sendCommentParent();
}
getDataComment();
};
const postDataChild = (id: any) => {
if (Number(userRoleId) < 1) {
router.push("/auth");
} else {
sendCommentChild(id);
}
};
const deleteData = (dataId: any) => {
deleteDataComment(dataId);
console.log(dataId);
};
const shimmer = (w: number, h: number) => `
<svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="g">
<stop stop-color="#bcbcbd" offset="20%" />
<stop stop-color="#f9fafb" offset="50%" />
<stop stop-color="#bcbcbd" offset="70%" />
</linearGradient>
</defs>
<rect width="${w}" height="${h}" fill="#bcbcbd" />
<rect id="r" width="${w}" height="${h}" fill="url(#g)" />
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
</svg>`;
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
return (
<>
<div className="p-4 lg:px-60 lg:p-12">
{/* Judul */}
<div className="flex flex-col mb-5">
<h1 className="text-base lg:text-lg mb-2">Index / Detail</h1>
<h1 className="flex flex-row font-bold text-center text-lg lg:text-2xl">{indeksData?.title}</h1>
</div>
{/* Gambar Utama */}
<div className="flex items-center justify-center">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={2560} height={1440} src={indeksData?.thumbnailLink} alt="Main" className="h-fit lg:h-[550px] w-full rounded-lg" />
</div>
{/* Footer Informasi */}
<div className="text-gray-500 flex border-t mt-4">
<div className="flex mt-2">
<p className="text-xs lg:text-sm mb-2 ">
{t("by")}&nbsp;<span className="font-semibold text-gray-500">{indeksData?.uploaderName}</span>&nbsp; | &nbsp;{t("updatedOn")} {indeksData?.createdAt} WIB &nbsp;
</p>
</div>
</div>
{/* Keterangan */}
<div className="w-auto">
<p className="font-light text-base lg:text-lg text-justify" dangerouslySetInnerHTML={{ __html: indeksData?.description }} />
</div>
</div>
{/* Comment */}
<div className="w-full">
<div className="flex flex-col py-5 p-0 lg:p-10 bg-[#f7f7f7] dark:bg-slate-600">
<div className="gap-5 flex flex-col px-4 lg:px-16">
<p className="flex items-start text-bases lg:text-lg">{t("comment")}</p>
<Textarea placeholder="Type your comments here." className="flex w-full" onChange={getInputValue} value={message} />
<button className="flex items-start bg-[#bb3523] text-white rounded-lg text-sm lg:text-base w-fit px-3 lg:px-4 py-1" onClick={() => postData()}>
{t("send")}
</button>
</div>
<div className="border-b-2 border-slate-300 mt-4 w-auto"></div>
<div>
{listComments?.map((data: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:px-14">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={512} height={512} className="h-10 lg:h-20 w-10 lg:w-20" src="/assets/img/user-avatar-yellow.svg" alt="#" />
<div className="border border-slate-300 w-full p-4 bg-white gap-1">
<p className="flex justify-between text-sm text-slate-500 lg:text-base border-b-2 border-slate-200 mb-2">
<b>{Number(data.commentFrom?.roleId) == 2 || Number(data.commentFrom?.roleId) == 3 || Number(data.commentFrom?.roleId) == 4 ? "HUMAS POLRI" : data.commentFrom?.fullname}</b>
{`${new Date(data.createdAt).getDate()}/${new Date(data.createdAt).getMonth() + 1}/${new Date(data.createdAt).getFullYear()} ${new Date(data.createdAt).getHours()}:${new Date(data.createdAt).getMinutes()}`}
</p>
<p className="text-slate-500 text-sm lg:text-base mb-4">{data.message}</p>
<div className="gap-3">
<a href="javascript:void(0)" className="text-xs lg:text-sm mr-2 bg-blue-500 text-white py-1 px-2 hover:bg-blue-300 hover:text-black rounded-md" onClick={() => showInput(`comment-id-${data.id}`)}>
{t("reply")}
</a>
<a
href="javascript:void(0)"
style={
data.commentFrom?.id == userId
? {}
: {
display: "none",
}
}
className="text-xs lg:text-sm bg-red-500 text-white py-1 px-2 hover:bg-red-300 hover:text-black rounded-md"
onClick={() => deleteData(data.id)}
>
{t("delete")}
</a>
</div>
</div>
</div>
<div className="flex flex-row px-4 pl-[55px] lg:px-14 lg:pl-[135px] mt-2" id={`comment-id-${data.id}`}>
<Input type="text" id={`input-comment-${data.id}`} className="p-4 focus:outline-none focus:border-sky-500" placeholder={t("enterReply")} />
<a href="javascript:void(0)" className="flex py-1 px-2 rounded-md items-center ml-2 bg-[#f7b357] text-white text-sm lg:text-base" onClick={() => postDataChild(data.id)}>
{t("send")}
</a>
</div>
{data.children.length > 0
? data.children?.map((child1: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-12 lg:pl-32">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={512} height={512} className="h-10 lg:h-20 w-10 lg:w-20" src="/assets/img/user-avatar-yellow.svg" alt="#" />
<div className="border border-slate-300 w-full p-4 bg-white gap-1">
<p className="flex justify-between text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
<b>{Number(child1.commentFrom?.roleId) == 2 || Number(child1.commentFrom?.roleId) == 3 || Number(child1.commentFrom?.roleId) == 4 ? "HUMAS POLRI" : child1.commentFrom?.fullname}</b>
{`${new Date(child1.createdAt).getDate()}/${new Date(child1.createdAt).getMonth() + 1}/${new Date(child1.createdAt).getFullYear()} ${new Date(child1.createdAt).getHours()}:${new Date(
child1.createdAt
).getMinutes()}`}
</p>
<p className="text-slate-500 text-sm mb-4">{child1.message}</p>
<div className="gap-3">
<a href="javascript:void(0)" className="mr-2 text-xs lg:text-sm bg-blue-500 text-white py-1 px-2 hover:bg-blue-300 hover:text-black rounded-md" onClick={() => showInput(`comment-id-${child1.id}`)}>
{t("reply")}
</a>
<a
href="javascript:void(0)"
className="text-xs lg:text-sm bg-red-500 text-white py-1 px-2 hover:bg-red-300 hover:text-black rounded-md"
style={
Number(child1.commentFrom?.id) == Number(userId)
? {}
: {
display: "none",
}
}
onClick={() => deleteData(child1.id)}
>
{t("delete")}
</a>
</div>
</div>
</div>
<div className="flex flex-row justify-center px-4 pl-[87px] lg:px-14 lg:pl-[205px] mt-2" id={`comment-id-${child1.id}`}>
<Input type="text" id={`input-comment-${child1.id}`} className="p-4 focus:outline-none focus:border-sky-500" placeholder={t("enterReply")} />
<a href="javascript:void(0)" className="flex text-sm lg:text-base py-1 px-2 rounded-md items-center ml-2 bg-[#f7b357] text-white" onClick={() => postDataChild(child1.id)}>
{t("send")}
</a>
</div>
{child1.children.length > 0
? child1.children?.map((child2: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-20 lg:pl-48">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={512} height={512} className="h-10 lg:h-20 w-10 lg:w-20" src="/assets/img/user-avatar-yellow.svg" alt="#" />
<div className="border border-slate-300 w-full p-4 bg-white gap-2">
<p className="flex justify-between text-slate-500 text-xs lg:text-base border-b-2 border-slate-200 mb-2">
<b>{Number(child2.commentFrom?.roleId) == 2 || Number(child2.commentFrom?.roleId) == 3 || Number(child2.commentFrom?.roleId) == 4 ? "HUMAS POLRI" : child2.commentFrom?.fullname}</b>
{`${new Date(child2.createdAt).getDate()}/${new Date(child2.createdAt).getMonth() + 1}/${new Date(child2.createdAt).getFullYear()} ${new Date(child2.createdAt).getHours()}:${new Date(
child2.createdAt
).getMinutes()}`}
</p>
<p className="text-slate-500 text-sm mb-4">{child2.message}</p>
<div>
<a href="javascript:void(0)" className="mr-2 text-xs lg:text-sm bg-blue-500 text-white py-1 px-2 hover:bg-blue-300 hover:text-black rounded-md" onClick={() => showInput("comment-id-" + child2.id)}>
{t("reply")}
</a>
<a
href="javascript:void(0)"
className="text-xs lg:text-sm bg-red-500 text-white py-1 px-2 hover:bg-red-300 hover:text-black rounded-md"
style={
Number(child2.commentFrom?.id) == Number(userId)
? {}
: {
display: "none",
}
}
onClick={() => deleteData(child2.id)}
>
{t("delete")}
</a>
</div>
</div>
</div>
<div className="flex flex-row px-4 pl-[120px] lg:px-14 lg:pl-[270px] mt-2" id={`comment-id-${child2.id}`}>
<Input type="text" id={`comment-id-${child2.id}`} className="p-4 focus:outline-none focus:border-sky-500" placeholder={t("enterReply")} />
<a href="javascript:void(0)" className="flex text-sm lg:text-base py-1 px-2 rounded-md items-center ml-2 bg-[#f7b357] text-white" onClick={() => postDataChild(child1.id)}>
{t("send")}
</a>
</div>
</div>
))
: ""}
</div>
))
: ""}
</div>
))}
</div>
</div>
{/* Konten Serupa */}
<div className="space-x-5 flex flex-col px-4 lg:px-16 py-16 gap-5">
<h1 className="font-bold text-base lg:text-xl px-4 lg:px-8"> {t("relatedPosts")}</h1>
<Carousel>
<CarouselContent className="w-full max-w-7xl">
{indexData?.map((relate: any) => (
<CarouselItem key={relate?.id} className="md:basis-1/2 lg:basis-1/3">
<Link href={`/indeks/detail/${relate?.slug}`} className="relative group overflow-hidden shadow-md hover:shadow-lg">
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
alt=""
width={2560}
height={1440}
src={relate?.thumbnailLink}
className="w-full rounded-lg h-40 lg:h-60 object-cover group-hover:scale-100 transition-transform duration-300"
/>
<div className="absolute bottom-0 left-0 right-0 bg-gray-600 border-l-4 border-[#bb3523] rounded-lg backdrop-blur-sm text-white p-2">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-sm px-4 py-1">{relate?.categoryName}</span>
<h1 className="text-sm lg:text-lg mb-2 font-semibold h-5 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible">{relate?.title}</h1>
<p className="flex flex-row items-center text-[10px] gap-2">
{formatDateToIndonesian(new Date(relate?.createdAt))} {relate?.timezone ? relate?.timezone : "WIB"} | <Icon icon="formkit:eye" width="15" height="15" /> {relate.clickCount}{" "}
</p>
</div>
</Link>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
</div>
</div>
</>
);
};
export default IndeksDetail;