Merge branch 'dev-sabda-v2' of https://gitlab.com/hanifsalafi/mediahub_redesign
This commit is contained in:
commit
e9c57fdd75
|
|
@ -1,827 +1,48 @@
|
|||
"use client";
|
||||
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||
import NewContent from "@/components/landing-page/new-content";
|
||||
import { Link, useRouter } from "@/i18n/routing";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { BarWave } from "react-cssfx-loading";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import {
|
||||
checkWishlistStatus,
|
||||
createPublicSuggestion,
|
||||
deletePublicSuggestion,
|
||||
deleteWishlist,
|
||||
getDetail,
|
||||
getDetailMetaData,
|
||||
getPublicSuggestionList,
|
||||
saveWishlist,
|
||||
} from "@/service/landing/landing";
|
||||
import { getCookiesDecrypt } from "@/lib/utils";
|
||||
import { close, error, loading, warning } from "@/config/swal";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { checkMaliciousText, getPublicLocaleTimestamp } from "@/utils/globals";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import Swal from "sweetalert2";
|
||||
import parse from "html-react-parser";
|
||||
import { postActivityLog } from "@/service/content/content";
|
||||
import { Metadata } from "next";
|
||||
import DetailImage from "@/components/main/image-detail";
|
||||
import DetailAudio from "@/components/main/audio-detail";
|
||||
|
||||
const DetailAudio = () => {
|
||||
const [selectedSize, setSelectedSize] = useState<string>("L");
|
||||
const [selectedTab, setSelectedTab] = useState("video");
|
||||
const t = useTranslations("LandingPage");
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const params = useParams();
|
||||
const slug = String(params?.slug);
|
||||
const [detailDataAudio, setDetailDataAudio] = useState<any>();
|
||||
const [isSaved, setIsSaved] = useState(false);
|
||||
const [wishlistId, setWishlistId] = useState();
|
||||
const { toast } = useToast();
|
||||
const [isDownloadAll, setIsDownloadAll] = useState(false);
|
||||
const [downloadProgress, setDownloadProgress] = useState(0);
|
||||
const [isFromSPIT, setIsFromSPIT] = useState(false);
|
||||
const [main, setMain] = useState<any>();
|
||||
const [resolutionSelected, setResolutionSelected] = useState("720");
|
||||
const [imageSizeSelected, setImageSizeSelected] = useState("l");
|
||||
const [message, setMessage] = useState("");
|
||||
const userRoleId = getCookiesDecrypt("urie");
|
||||
const [listSuggestion, setListSuggestion] = useState<any>();
|
||||
const [visibleInput, setVisibleInput] = useState<string | null>(null);
|
||||
const MySwal = withReactContent(Swal);
|
||||
interface Size {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
const userId = getCookiesDecrypt("uie");
|
||||
|
||||
useEffect(() => {
|
||||
initFetch();
|
||||
checkWishlist();
|
||||
sendActivityLog(2);
|
||||
}, []);
|
||||
|
||||
const initFetch = async () => {
|
||||
const response = await getDetail(String(slug));
|
||||
console.log("detailAudio", response);
|
||||
setIsFromSPIT(response?.data?.data?.isFromSPIT);
|
||||
setMain({
|
||||
id: response?.data?.data?.files[0]?.id,
|
||||
type: response?.data?.data?.fileType.name,
|
||||
url:
|
||||
Number(response?.data?.data?.fileType?.id) == 4
|
||||
? response?.data?.data?.files[0]?.secondaryUrl
|
||||
: Number(response?.data?.data?.fileType?.id) == 2
|
||||
? `${process.env.NEXT_PUBLIC_API}/media/view?id=${response?.data?.data?.files[0]?.id}&operation=file&type=video`
|
||||
: response?.data?.data?.files[0]?.url,
|
||||
thumbnailFileUrl: response?.data?.data?.files[0]?.thumbnailFileUrl,
|
||||
names: response?.data?.data?.files[0]?.fileName,
|
||||
format: response?.data?.data?.files[0]?.format,
|
||||
widthPixel: response?.data?.data?.files[0]?.widthPixel,
|
||||
heightPixel: response?.data?.data?.files[0]?.heightPixel,
|
||||
size: response?.data?.data?.files[0]?.size,
|
||||
caption: response?.data?.data?.files[0]?.caption,
|
||||
});
|
||||
setDetailDataAudio(response?.data?.data);
|
||||
type Props = {
|
||||
params: {
|
||||
title: string;
|
||||
slug: string;
|
||||
description: string;
|
||||
thumbnailLink: string;
|
||||
};
|
||||
|
||||
const doBookmark = async () => {
|
||||
if (userId) {
|
||||
const data = {
|
||||
mediaUploadId: slug?.split("-")?.[0],
|
||||
};
|
||||
|
||||
loading();
|
||||
const res = await saveWishlist(data);
|
||||
if (res?.error) {
|
||||
error(res.message);
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
toast({
|
||||
title: "Konten berhasil disimpan",
|
||||
});
|
||||
checkWishlist();
|
||||
} else {
|
||||
router.push("/auth");
|
||||
}
|
||||
};
|
||||
async function checkWishlist() {
|
||||
if (userId) {
|
||||
const res = await checkWishlistStatus(slug.split("-")?.[0]);
|
||||
console.log(res?.data?.data);
|
||||
const isAlreadyOnWishlist = res?.data?.data !== "-1";
|
||||
setWishlistId(res?.data?.data);
|
||||
setIsSaved(isAlreadyOnWishlist);
|
||||
}
|
||||
}
|
||||
|
||||
const handleDeleteWishlist = async () => {
|
||||
if (userId) {
|
||||
loading();
|
||||
const res = await deleteWishlist(wishlistId);
|
||||
|
||||
if (res?.error) {
|
||||
error(res.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
toast({
|
||||
title: "Konten berhasil dihapus",
|
||||
});
|
||||
close();
|
||||
checkWishlist();
|
||||
} else {
|
||||
router.push("/auth");
|
||||
}
|
||||
};
|
||||
|
||||
async function sendActivityLog(activityTypeId: number) {
|
||||
const data = {
|
||||
activityTypeId,
|
||||
mediaId: slug.split("-")?.[0],
|
||||
url: window.location.href,
|
||||
};
|
||||
// set activity
|
||||
await postActivityLog(data);
|
||||
}
|
||||
|
||||
const handleDownload = () => {
|
||||
if (downloadProgress === 0) {
|
||||
if (!userId) {
|
||||
router.push("/auth/login");
|
||||
} else {
|
||||
sendActivityLog(2);
|
||||
sendActivityLog(3);
|
||||
|
||||
if (isDownloadAll) {
|
||||
let url: string;
|
||||
const baseId = slug.split("-")?.[0];
|
||||
|
||||
// if (type === "1") {
|
||||
// url = `${process.env.NEXT_PUBLIC_API}/media/file/download-zip?id=${baseId}&resolution=${resolutionSelected}`;
|
||||
// } else if (type === "2") {
|
||||
// url = `${process.env.NEXT_PUBLIC_API}/media/file/download-zip?id=${baseId}&resolution=${imageSizeSelected}`;
|
||||
// } else {
|
||||
url = `${process.env.NEXT_PUBLIC_API}/media/file/download-zip?id=${baseId}`;
|
||||
// }
|
||||
|
||||
downloadFile(url, "FileDownload.zip");
|
||||
} else {
|
||||
if (isFromSPIT && main?.url?.includes("spit.humas")) {
|
||||
downloadFile(`${main?.url}`, `${main.names}`);
|
||||
} else {
|
||||
downloadFile(`${main?.url}`, `${main.names}`);
|
||||
}
|
||||
}
|
||||
// } else if (type === "1" && resolutionSelected?.length > 0) {
|
||||
// if (isFromSPIT && main?.url?.includes("spit.humas")) {
|
||||
// downloadFile(`${main?.url}`, `${main.names}`);
|
||||
// } else {
|
||||
// const url = `${process.env.NEXT_PUBLIC_API}/media/view?id=${main?.id}&operation=file&type=video&resolution=${resolutionSelected}p`;
|
||||
// downloadFile(url, `${main.names}`);
|
||||
// }
|
||||
// } else if (type === "2" && imageSizeSelected?.length > 0) {
|
||||
// const url = `${process.env.NEXT_PUBLIC_API}/media/view?id=${main?.id}&operation=file&type=image&resolution=${imageSizeSelected}`;
|
||||
// downloadFile(url, `${main.names}`);
|
||||
// } else if (type === "3" || type === "4") {
|
||||
// downloadFile(`${main?.url}`, `${main.names}`);
|
||||
// }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const downloadFile = (fileUrl: string, name: string) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open("GET", fileUrl, true);
|
||||
xhr.responseType = "blob";
|
||||
|
||||
xhr.addEventListener("progress", (event) => {
|
||||
if (event.lengthComputable) {
|
||||
const percentCompleted = Math.round((event.loaded / event.total) * 100);
|
||||
setDownloadProgress(percentCompleted);
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener("readystatechange", () => {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
const contentType =
|
||||
xhr.getResponseHeader("content-type") || "application/octet-stream";
|
||||
const extension = contentType.split("/")[1];
|
||||
const filename = `${name}.${extension}`;
|
||||
|
||||
const blob = new Blob([xhr.response], {
|
||||
type: contentType,
|
||||
});
|
||||
const downloadUrl = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
|
||||
a.href = downloadUrl;
|
||||
a.download = filename;
|
||||
document.body.append(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
}
|
||||
});
|
||||
|
||||
xhr.onloadend = () => {
|
||||
setDownloadProgress(0);
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
const sizes = [
|
||||
{ label: "XL", value: "3198 x 1798 px" },
|
||||
{ label: "L", value: "2399 x 1349 px" },
|
||||
{ label: "M", value: "1599 x 899 px" },
|
||||
{ label: "S", value: "1066 x 599 px" },
|
||||
{ label: "XS", value: "800 x 450 px" },
|
||||
];
|
||||
async function sendSuggestionParent() {
|
||||
if (message?.length > 3) {
|
||||
loading();
|
||||
const data = {
|
||||
mediaUploadId: slug?.split("-")?.[0],
|
||||
message,
|
||||
parentId: null,
|
||||
};
|
||||
|
||||
const response = await createPublicSuggestion(data);
|
||||
|
||||
console.log(response);
|
||||
setMessage("");
|
||||
|
||||
const responseGet = await getPublicSuggestionList(slug?.split("-")?.[0]);
|
||||
console.log(responseGet?.data?.data);
|
||||
setListSuggestion(responseGet?.data?.data);
|
||||
|
||||
// Hapus nilai semua input secara manual jika perlu
|
||||
const inputs = document.querySelectorAll("input");
|
||||
inputs.forEach((input) => {
|
||||
input.value = "";
|
||||
});
|
||||
|
||||
close();
|
||||
}
|
||||
}
|
||||
const getInputValue = (e: any) => {
|
||||
const message = e.target.value;
|
||||
console.log(message);
|
||||
setMessage(message);
|
||||
};
|
||||
const postData = () => {
|
||||
const checkMessage = checkMaliciousText(message);
|
||||
if (checkMessage == "") {
|
||||
if (Number(userRoleId) < 1 || userRoleId == undefined) {
|
||||
router.push("/auth");
|
||||
} else {
|
||||
sendSuggestionParent();
|
||||
}
|
||||
} else {
|
||||
warning(checkMessage);
|
||||
}
|
||||
};
|
||||
function addDefaultProfile(ev: any) {
|
||||
ev.target.src = "/assets/avatar-profile.png";
|
||||
}
|
||||
const showInput = (e: any) => {
|
||||
console.log(document.querySelector(`#${e}`)?.classList);
|
||||
document.querySelector(`#${e}`)?.classList.toggle("none");
|
||||
setVisibleInput(visibleInput === e ? null : e);
|
||||
};
|
||||
async function sendSuggestionChild(parentId: any) {
|
||||
const inputElement = document.querySelector(
|
||||
`#input-comment-${parentId}`
|
||||
) as HTMLInputElement;
|
||||
|
||||
if (inputElement && inputElement.value.length > 3) {
|
||||
loading();
|
||||
const data = {
|
||||
mediaUploadId: slug?.split("-")?.[0],
|
||||
message: inputElement.value,
|
||||
parentId,
|
||||
};
|
||||
|
||||
console.log(data);
|
||||
const response = await createPublicSuggestion(data);
|
||||
console.log(response);
|
||||
const responseGet: any = await getPublicSuggestionList(
|
||||
slug?.split("-")?.[0]
|
||||
);
|
||||
console.log(responseGet?.data?.data);
|
||||
setListSuggestion(responseGet?.data?.data);
|
||||
|
||||
// Reset input field
|
||||
inputElement.value = "";
|
||||
|
||||
// document.querySelector("#comment-id-" + parentId)?.style.display = "none";
|
||||
|
||||
close();
|
||||
}
|
||||
}
|
||||
async function deleteDataSuggestion(dataId: any) {
|
||||
loading();
|
||||
const response = await deletePublicSuggestion(dataId);
|
||||
console.log(response);
|
||||
const responseGet = await getPublicSuggestionList(slug.split("-")?.[0]);
|
||||
console.log(responseGet?.data?.data);
|
||||
setListSuggestion(responseGet?.data?.data);
|
||||
close();
|
||||
}
|
||||
const deleteData = (dataId: any) => {
|
||||
MySwal.fire({
|
||||
title: "Delete Comment",
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
cancelButtonColor: "#3085d6",
|
||||
confirmButtonColor: "#d33",
|
||||
confirmButtonText: "Delete",
|
||||
}).then((result: any) => {
|
||||
if (result.isConfirmed) {
|
||||
deleteDataSuggestion(dataId);
|
||||
console.log(dataId);
|
||||
}
|
||||
});
|
||||
};
|
||||
const postDataChild = (id: any) => {
|
||||
const checkMessage = checkMaliciousText(message);
|
||||
if (checkMessage == "") {
|
||||
if (Number(userRoleId) < 1 || userRoleId == undefined) {
|
||||
router.push("/auth");
|
||||
} else {
|
||||
sendSuggestionChild(id);
|
||||
}
|
||||
} else {
|
||||
warning(checkMessage);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<div className="min-h-screen px-4 md:px-24 py-4">
|
||||
{/* Container Utama */}
|
||||
<div className="rounded-md overflow-hidden md:flex">
|
||||
{/* Bagian Kiri */}
|
||||
<div className="md:w-3/4">
|
||||
<div className="relative flex justify-center">
|
||||
<img src="/assets/audio-btn.png" />
|
||||
<BarWave
|
||||
color="#ffc831"
|
||||
width="60px"
|
||||
height="25px"
|
||||
duration="2s"
|
||||
/>
|
||||
<div className="absolute top-4 left-4"></div>
|
||||
</div>
|
||||
{/* Footer Informasi */}
|
||||
<div className="p-4 text-sm text-gray-500 flex justify-between items-center border-t mt-4">
|
||||
<p className="flex flex-row items-center">
|
||||
oleh
|
||||
<span className="font-semibold text-black">
|
||||
{detailDataAudio?.uploadedBy?.userLevel?.name}
|
||||
</span>
|
||||
| Diupdate pada {detailDataAudio?.updatedAt}{" "}
|
||||
WIB |
|
||||
<Icon icon="formkit:eye" width="15" height="15" />
|
||||
|
||||
{detailDataAudio?.clickCount}
|
||||
</p>
|
||||
<p>Kreator: {detailDataAudio?.creatorName}</p>
|
||||
</div>
|
||||
{/* Keterangan */}
|
||||
<div className="md:w-3/4">
|
||||
<h1 className="flex flex-row font-bold text-2xl mx-5 my-8">
|
||||
{detailDataAudio?.title}
|
||||
</h1>
|
||||
<div
|
||||
className="font-light text-justify"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: detailDataAudio?.htmlDescription,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bagian Kanan */}
|
||||
<div className="md:w-1/4 p-4 h-fit bg-gray-300 rounded-lg mx-4">
|
||||
{isSaved ? (
|
||||
<a
|
||||
onClick={() => handleDeleteWishlist()}
|
||||
className="flex flex-col mb-3 items-center justify-center cursor-pointer"
|
||||
>
|
||||
<Icon icon="material-symbols:bookmark" width={40} />
|
||||
<p className="text-base lg:text-lg">Hapus</p>
|
||||
</a>
|
||||
) : (
|
||||
<a
|
||||
onClick={() => doBookmark()}
|
||||
className="flex flex-col mb-3 items-center justify-center cursor-pointer"
|
||||
>
|
||||
<Icon icon="material-symbols:bookmark-outline" width={40} />
|
||||
<p className="text-base lg:text-lg">Simpan</p>
|
||||
</a>
|
||||
)}
|
||||
|
||||
{/* garis */}
|
||||
<div className="border-t border-black my-4"></div>
|
||||
|
||||
<Link
|
||||
href={`/all/filter?title=polda&category=${detailDataAudio?.category.id}`}
|
||||
className="bg-red-600 text-white text-xs font-bold px-3 py-3 my-3 flex justify-center items-center rounded"
|
||||
>
|
||||
{detailDataAudio?.category?.name}
|
||||
</Link>
|
||||
|
||||
<div className="flex justify-center flex-wrap gap-2 mb-4">
|
||||
{detailDataAudio?.tags?.split(",").map((tag: string) => (
|
||||
<a
|
||||
onClick={() => router.push(`/all/filter?tag=${tag}`)}
|
||||
key={tag}
|
||||
className="bg-gray-200 text-gray-700 text-xs px-3 py-1 rounded-full cursor-pointer hover:bg-gray-500"
|
||||
>
|
||||
{tag}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="border-t border-black my-4"></div>
|
||||
|
||||
{/* Opsi Ukuran Foto */}
|
||||
<h4 className="flex text-lg justify-center items-center font-semibold my-3">
|
||||
Opsi Ukuran Audio
|
||||
</h4>
|
||||
|
||||
<div className="border-t border-black my-4"></div>
|
||||
|
||||
<div className="space-y-2">
|
||||
{sizes.map((size: any) => (
|
||||
<div className="flex flex-row justify-between">
|
||||
<div
|
||||
key={size.label}
|
||||
className="items-center flex flex-row gap-2 cursor-pointer"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="size"
|
||||
value={size.label}
|
||||
checked={selectedSize === size.label}
|
||||
onChange={() => setSelectedSize(size.label)}
|
||||
className="text-red-600 focus:ring-red-600"
|
||||
/>
|
||||
<div className="text-sm">{size.label}</div>
|
||||
</div>
|
||||
<div className="">
|
||||
<div className="text-sm">{size.value}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Download Semua */}
|
||||
<div className="mt-4">
|
||||
<label className="flex items-center space-x-2 text-sm">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="text-red-600 focus:ring-red-600"
|
||||
onChange={() => setIsDownloadAll(!isDownloadAll)}
|
||||
/>
|
||||
<span>Download Semua File?</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Tombol Download */}
|
||||
<button
|
||||
onClick={handleDownload}
|
||||
className="mt-4 bg-red-600 text-white w-full py-2 flex justify-center items-center gap-1 rounded-md text-sm hover:bg-red-700"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="white"
|
||||
d="m12 16l-5-5l1.4-1.45l2.6 2.6V4h2v8.15l2.6-2.6L17 11zm-6 4q-.825 0-1.412-.587T4 18v-3h2v3h12v-3h2v3q0 .825-.587 1.413T18 20z"
|
||||
/>
|
||||
</svg>
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full mb-8">
|
||||
{/* Comment */}
|
||||
{/* <div className="flex flex-col my-16 gap-5 p-10 bg-gray-300">
|
||||
<p className="flex items-start text-lg">Berikan Komentar</p>
|
||||
<Textarea placeholder="Type your comments here." className="flex items-start justify-center" />
|
||||
<button className="flex items-start bg-[#bb3523] rounded-lg w-fit px-4 py-1">Kirim</button>
|
||||
</div> */}
|
||||
<div className="flex flex-col my-16 p-4 lg:p-10 bg-[#f7f7f7]">
|
||||
<div className="gap-5 flex flex-col px-4 lg:px-14">
|
||||
<p className="flex items-start text-lg">{t("comment")}</p>
|
||||
<Textarea
|
||||
placeholder="Type your comments here."
|
||||
className="flex w-full pb-12"
|
||||
onChange={getInputValue}
|
||||
/>
|
||||
<button
|
||||
onClick={() => postData()}
|
||||
className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1"
|
||||
>
|
||||
{t("send")}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="border-b-2 border-slate-300 mt-4 w-auto"></div>
|
||||
|
||||
<div>
|
||||
{listSuggestion?.map((data: any) => (
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-row mt-2 px-4 lg:px-14">
|
||||
<img
|
||||
src={data?.suggestionFrom?.profilePictureUrl}
|
||||
className="h-12 lg:h-16 w-12 lg:w-16 mr-2"
|
||||
onError={addDefaultProfile}
|
||||
alt=""
|
||||
/>
|
||||
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
|
||||
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
|
||||
{Number(data.suggestionFrom?.roleId) == 2 ||
|
||||
Number(data.suggestionFrom?.roleId) == 3 ||
|
||||
Number(data.suggestionFrom?.roleId) == 4
|
||||
? "HUMAS POLRI"
|
||||
: data.suggestionFrom?.fullname}
|
||||
{getPublicLocaleTimestamp(new Date(data.createdAt))}
|
||||
</p>
|
||||
<p className="text-slate-500 text-[13px] lg:text-sm mb-4">
|
||||
{data?.message}
|
||||
</p>
|
||||
<div>
|
||||
<a
|
||||
style={
|
||||
Number(data.suggestionFrom?.id) == Number(userId)
|
||||
? {
|
||||
display: "none",
|
||||
}
|
||||
: {}
|
||||
}
|
||||
onClick={() => showInput(`comment-id-${data.id}`)}
|
||||
className="mr-2"
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("reply")}
|
||||
</small>
|
||||
</a>
|
||||
{Number(data.suggestionFrom?.id) == Number(userId) ||
|
||||
Number(userRoleId) == 2 ? (
|
||||
<a onClick={() => deleteData(data.id)}>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("delete")}
|
||||
</small>
|
||||
</a>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{visibleInput === `comment-id-${data.id}` && (
|
||||
<div
|
||||
id={`comment-id-${data.id}`}
|
||||
className="px-4 pl-[72px] lg:px-14 lg:pl-32 mt-2 "
|
||||
>
|
||||
<Textarea
|
||||
id={`input-comment-${data.id}`}
|
||||
className="p-4 focus:outline-none focus:border-sky-500"
|
||||
placeholder={t("enterReply")}
|
||||
/>
|
||||
<div className="flex flex-row gap-3">
|
||||
<a onClick={() => postDataChild(data.id)}>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 mt-2 cursor-pointer">
|
||||
{t("send")}
|
||||
</small>
|
||||
</a>
|
||||
<a onClick={() => showInput(`comment-id-${data.id}`)}>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg mt-2 w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("cancel")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</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-16 lg:pl-32">
|
||||
<img
|
||||
src={child1.suggestionFrom?.profilePictureUrl}
|
||||
onError={addDefaultProfile}
|
||||
alt=""
|
||||
className="h-10 lg:h-16 w-10 lg:w-16 mr-2"
|
||||
/>
|
||||
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
|
||||
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
|
||||
{" "}
|
||||
<b>
|
||||
{Number(child1.suggestionFrom?.roleId) == 2 ||
|
||||
Number(child1.suggestionFrom?.roleId) == 3 ||
|
||||
Number(child1.suggestionFrom?.roleId) == 4
|
||||
? "HUMAS POLRI"
|
||||
: child1.suggestionFrom?.fullname}
|
||||
</b>{" "}
|
||||
{getPublicLocaleTimestamp(
|
||||
new Date(child1.createdAt)
|
||||
)}
|
||||
</p>
|
||||
<p className="text-slate-500 text-[13px] lg:text-sm mb-4">
|
||||
{parse(String(child1?.message))}
|
||||
</p>
|
||||
<div>
|
||||
<a
|
||||
style={
|
||||
Number(child1.suggestionFrom?.id) ==
|
||||
Number(userId)
|
||||
? {
|
||||
display: "none",
|
||||
}
|
||||
: {}
|
||||
}
|
||||
onClick={() =>
|
||||
showInput(`comment-id-${child1.id}`)
|
||||
}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("reply")}
|
||||
</small>
|
||||
</a>
|
||||
<a
|
||||
style={
|
||||
Number(child1.suggestionFrom?.id) ==
|
||||
Number(userId)
|
||||
? {}
|
||||
: {
|
||||
display: "none",
|
||||
}
|
||||
}
|
||||
onClick={() => deleteData(child1.id)}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("delete")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{visibleInput === `comment-id-${child1.id}` && (
|
||||
<div
|
||||
id={`comment-id-${child1.id}`}
|
||||
className="px-4 lg:px-14 pl-28 lg:pl-[200px]"
|
||||
>
|
||||
<Textarea
|
||||
name=""
|
||||
className="mt-2 "
|
||||
id={`input-comment-${child1.id}`}
|
||||
placeholder={t("enterReply")}
|
||||
/>
|
||||
<div className="flex flex-row mt-2 gap-3">
|
||||
<a onClick={() => postDataChild(child1.id)}>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("send")}
|
||||
</small>
|
||||
</a>
|
||||
<a
|
||||
onClick={() =>
|
||||
showInput(`comment-id-${child1.id}`)
|
||||
}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("cancel")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{child1.children.length > 0
|
||||
? child1.children?.map((child2: any) => (
|
||||
<div className="">
|
||||
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-28 lg:pl-48">
|
||||
<img
|
||||
src={
|
||||
child2.suggestionFrom?.profilePictureUrl
|
||||
}
|
||||
className="h-9 lg:h-16 w-9 lg:w-16 mr-2"
|
||||
onError={addDefaultProfile}
|
||||
alt=""
|
||||
/>
|
||||
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
|
||||
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
|
||||
{" "}
|
||||
<b>
|
||||
{Number(
|
||||
child2.suggestionFrom?.roleId
|
||||
) == 2 ||
|
||||
Number(child2.suggestionFrom?.roleId) ==
|
||||
3 ||
|
||||
Number(child2.suggestionFrom?.roleId) ==
|
||||
4
|
||||
? "HUMAS POLRI"
|
||||
: child2.suggestionFrom?.fullname}
|
||||
</b>{" "}
|
||||
{getPublicLocaleTimestamp(
|
||||
new Date(child2.createdAt)
|
||||
)}
|
||||
</p>
|
||||
<p className="text-slate-500 text-sm mb-4">
|
||||
{parse(String(child2?.message))}
|
||||
</p>
|
||||
<div>
|
||||
<a
|
||||
style={
|
||||
Number(child2.suggestionFrom?.id) ==
|
||||
Number(userId)
|
||||
? {
|
||||
display: "none",
|
||||
}
|
||||
: {}
|
||||
}
|
||||
onClick={() =>
|
||||
showInput(`comment-id-${child2.id}`)
|
||||
}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("reply")}
|
||||
</small>
|
||||
</a>
|
||||
<a
|
||||
style={
|
||||
Number(child2.suggestionFrom?.id) ==
|
||||
Number(userId)
|
||||
? {}
|
||||
: {
|
||||
display: "none",
|
||||
}
|
||||
}
|
||||
onClick={() => deleteData(child2.id)}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("delete")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{visibleInput === `comment-id-${child2.id}` && (
|
||||
<div
|
||||
id={`comment-id-${child2.id}`}
|
||||
className="px-4 lg:px-14 pl-40 lg:pl-[265px]"
|
||||
>
|
||||
<Textarea
|
||||
name=""
|
||||
id={`input-comment-${child2.id}`}
|
||||
className="my-2"
|
||||
placeholder="Masukkan balasan anda"
|
||||
/>
|
||||
<div className="flex flex-row gap-3">
|
||||
<a
|
||||
onClick={() => postDataChild(child2.id)}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("send")}
|
||||
</small>
|
||||
</a>
|
||||
<a
|
||||
onClick={() =>
|
||||
showInput(`comment-id-${child2.id}`)
|
||||
}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("cancel")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
: ""}
|
||||
</div>
|
||||
))
|
||||
: ""}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Konten Serupa */}
|
||||
<div className="px-4">
|
||||
<NewContent group="polda" type={"similar"} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailAudio;
|
||||
export async function generateMetadata({ params }: any): Promise<Metadata> {
|
||||
const slug = String(params?.slug);
|
||||
const res = await getDetailMetaData(String(slug));
|
||||
const audio = res?.data?.data;
|
||||
// console.log("image", image);
|
||||
return {
|
||||
title: audio.title,
|
||||
description: audio.description,
|
||||
openGraph: {
|
||||
title: audio?.title,
|
||||
description: audio?.description,
|
||||
audio: [`${audio?.thumbnailLink}`],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default async function DetailInfo({ params }: Props) {
|
||||
return <DetailAudio />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -627,8 +627,13 @@ const FilterPage = () => {
|
|||
<div className="flex flex-col gap-3">
|
||||
{audioData?.map((audio: any) => (
|
||||
<div key={audio?.id}>
|
||||
<Link
|
||||
href={`/audio/detail/${audio?.slug}`}
|
||||
<div
|
||||
// href={`/audio/detail/${audio?.slug}`}
|
||||
onClick={() =>
|
||||
router.push(
|
||||
prefixPath + `/audio/detail/${audio?.slug}`
|
||||
)
|
||||
}
|
||||
className="flex flex-row items-center bg-white dark:bg-gray-800 cursor-pointer shadow-md rounded-lg p-4 gap-4 w-full"
|
||||
>
|
||||
<div className="flex justify-center lg:justify-between w-full gap-2 lg:gap-6">
|
||||
|
|
@ -703,7 +708,7 @@ const FilterPage = () => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -692,8 +692,13 @@ const FilterPage = () => {
|
|||
{documentData?.length > 0 ? (
|
||||
<div className=" grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{documentData?.map((document: any) => (
|
||||
<Link
|
||||
href={`/document/detail/${document?.slug}`}
|
||||
<div
|
||||
// href={`/document/detail/${document?.slug}`}
|
||||
onClick={() =>
|
||||
router.push(
|
||||
prefixPath + `/document/detail/${document?.slug}`
|
||||
)
|
||||
}
|
||||
key={document?.id}
|
||||
className="flex flex-col bg-yellow-500 sm:flex-row items-center dark:bg-gray-800 cursor-pointer shadow-md rounded-lg p-4 gap-4 w-full"
|
||||
>
|
||||
|
|
@ -739,7 +744,7 @@ const FilterPage = () => {
|
|||
Download Dokumen
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -1,921 +1,51 @@
|
|||
"use client";
|
||||
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||
import NewContent from "@/components/landing-page/new-content";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { getCookiesDecrypt } from "@/lib/utils";
|
||||
import { close, error, loading, warning } from "@/config/swal";
|
||||
import {
|
||||
checkWishlistStatus,
|
||||
createPublicSuggestion,
|
||||
deletePublicSuggestion,
|
||||
deleteWishlist,
|
||||
getDetail,
|
||||
getDetailMetaData,
|
||||
getPublicSuggestionList,
|
||||
saveWishlist,
|
||||
} from "@/service/landing/landing";
|
||||
import { Link, useRouter } from "@/i18n/routing";
|
||||
import Image from "next/image";
|
||||
import { useTranslations } from "next-intl";
|
||||
import {
|
||||
checkMaliciousText,
|
||||
formatDateToIndonesian,
|
||||
getPublicLocaleTimestamp,
|
||||
} from "@/utils/globals";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import Swal from "sweetalert2";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import parse from "html-react-parser";
|
||||
import { postActivityLog } from "@/service/content/content";
|
||||
import { Metadata } from "next";
|
||||
import DetailImage from "@/components/main/image-detail";
|
||||
|
||||
const DetailInfo = () => {
|
||||
const MySwal = withReactContent(Swal);
|
||||
const [selectedSize, setSelectedSize] = useState<string>("L");
|
||||
const [selectedTab, setSelectedTab] = useState("video");
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const params = useParams();
|
||||
const slug = String(params?.slug);
|
||||
const [detailDataImage, setDetailDataImage] = useState<any>();
|
||||
const [selectedImage, setSelectedImage] = useState(0);
|
||||
const [isSaved, setIsSaved] = useState(false);
|
||||
const [wishlistId, setWishlistId] = useState();
|
||||
const { toast } = useToast();
|
||||
const [isDownloadAll, setIsDownloadAll] = useState(false);
|
||||
const [downloadProgress, setDownloadProgress] = useState(0);
|
||||
const [isFromSPIT, setIsFromSPIT] = useState(false);
|
||||
const [main, setMain] = useState<any>();
|
||||
const [resolutionSelected, setResolutionSelected] = useState("720");
|
||||
const [imageSizeSelected, setImageSizeSelected] = useState("l");
|
||||
const userId = getCookiesDecrypt("uie");
|
||||
const [content, setContent] = useState<any>([]);
|
||||
const [emailShareList, setEmailShareList] = useState<any>();
|
||||
const [emailShareInput, setEmailShareInput] = useState<any>();
|
||||
const [emailMessageInput, setEmailMessageInput] = useState();
|
||||
const searchParams = useSearchParams();
|
||||
const [width, setWidth] = useState<any>();
|
||||
const userRoleId = getCookiesDecrypt("urie");
|
||||
const [message, setMessage] = useState("");
|
||||
const [listSuggestion, setListSuggestion] = useState<any>();
|
||||
const [isLoading, setIsLoading] = useState<any>(true);
|
||||
const [visibleInput, setVisibleInput] = useState(null);
|
||||
let typeString = "image";
|
||||
const t = useTranslations("LandingPage");
|
||||
const poldaName = params?.polda_name;
|
||||
const satkerName = params?.satker_name;
|
||||
interface Size {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
initFetch();
|
||||
checkWishlist();
|
||||
sendActivityLog(2);
|
||||
}, []);
|
||||
|
||||
const initFetch = async () => {
|
||||
const response = await getDetail(String(slug));
|
||||
console.log("detailImage", response);
|
||||
setIsFromSPIT(response?.data?.data?.isFromSPIT);
|
||||
setMain({
|
||||
id: response?.data?.data?.files[0]?.id,
|
||||
type: response?.data?.data?.fileType.name,
|
||||
url:
|
||||
Number(response?.data?.data?.fileType?.id) == 4
|
||||
? response?.data?.data?.files[0]?.secondaryUrl
|
||||
: Number(response?.data?.data?.fileType?.id) == 2
|
||||
? `${process.env.NEXT_PUBLIC_API}/media/view?id=${response?.data?.data?.files[0]?.id}&operation=file&type=video`
|
||||
: response?.data?.data?.files[0]?.url,
|
||||
thumbnailFileUrl: response?.data?.data?.files[0]?.thumbnailFileUrl,
|
||||
names: response?.data?.data?.files[0]?.fileName,
|
||||
format: response?.data?.data?.files[0]?.format,
|
||||
widthPixel: response?.data?.data?.files[0]?.widthPixel,
|
||||
heightPixel: response?.data?.data?.files[0]?.heightPixel,
|
||||
size: response?.data?.data?.files[0]?.size,
|
||||
caption: response?.data?.data?.files[0]?.caption,
|
||||
});
|
||||
setDetailDataImage(response?.data?.data);
|
||||
type Props = {
|
||||
params: {
|
||||
title: string;
|
||||
slug: string;
|
||||
description: string;
|
||||
thumbnailLink: string;
|
||||
};
|
||||
|
||||
const doBookmark = async () => {
|
||||
if (userId) {
|
||||
const data = {
|
||||
mediaUploadId: slug?.split("-")?.[0],
|
||||
};
|
||||
|
||||
loading();
|
||||
const res = await saveWishlist(data);
|
||||
if (res?.error) {
|
||||
error(res.message);
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
toast({
|
||||
title: "Konten berhasil disimpan",
|
||||
});
|
||||
checkWishlist();
|
||||
} else {
|
||||
router.push("/auth");
|
||||
}
|
||||
};
|
||||
async function checkWishlist() {
|
||||
if (userId) {
|
||||
const res = await checkWishlistStatus(slug.split("-")?.[0]);
|
||||
console.log(res?.data?.data);
|
||||
const isAlreadyOnWishlist = res?.data?.data !== "-1";
|
||||
setWishlistId(res?.data?.data);
|
||||
setIsSaved(isAlreadyOnWishlist);
|
||||
}
|
||||
}
|
||||
|
||||
const handleDeleteWishlist = async () => {
|
||||
if (userId) {
|
||||
loading();
|
||||
const res = await deleteWishlist(wishlistId);
|
||||
|
||||
if (res?.error) {
|
||||
error(res.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
toast({
|
||||
title: "Konten berhasil dihapus",
|
||||
});
|
||||
close();
|
||||
checkWishlist();
|
||||
} else {
|
||||
router.push("/auth");
|
||||
}
|
||||
};
|
||||
|
||||
const getInputValue = (e: any) => {
|
||||
const message = e.target.value;
|
||||
console.log(message);
|
||||
setMessage(message);
|
||||
};
|
||||
|
||||
const sizes = [
|
||||
{ label: "XL", value: "3198 x 1798 px" },
|
||||
{ label: "L", value: "2399 x 1349 px" },
|
||||
{ label: "M", value: "1599 x 899 px" },
|
||||
{ label: "S", value: "1066 x 599 px" },
|
||||
{ label: "XS", value: "800 x 450 px" },
|
||||
];
|
||||
|
||||
async function sendActivityLog(activityTypeId: number) {
|
||||
const data = {
|
||||
activityTypeId,
|
||||
mediaId: slug.split("-")?.[0],
|
||||
url: window.location.href,
|
||||
};
|
||||
// set activity
|
||||
await postActivityLog(data);
|
||||
}
|
||||
|
||||
function addDefaultProfile(ev: any) {
|
||||
ev.target.src = "/assets/avatar-profile.png";
|
||||
}
|
||||
|
||||
const handleDownload = () => {
|
||||
if (downloadProgress === 0) {
|
||||
if (!userId) {
|
||||
router.push("/auth/login");
|
||||
} else {
|
||||
sendActivityLog(2);
|
||||
sendActivityLog(3);
|
||||
|
||||
if (isDownloadAll) {
|
||||
let url: string;
|
||||
const baseId = slug.split("-")?.[0];
|
||||
|
||||
// if (type === "1") {
|
||||
// url = `${process.env.NEXT_PUBLIC_API}/media/file/download-zip?id=${baseId}&resolution=${resolutionSelected}`;
|
||||
// } else if (type === "2") {
|
||||
url = `${process.env.NEXT_PUBLIC_API}/media/file/download-zip?id=${baseId}&resolution=${imageSizeSelected}`;
|
||||
// } else {
|
||||
// url = `${process.env.NEXT_PUBLIC_API}/media/file/download-zip?id=${baseId}`;
|
||||
// }
|
||||
|
||||
downloadFile(url, "FileDownload.zip");
|
||||
} else {
|
||||
if (isFromSPIT && main?.url?.includes("spit.humas")) {
|
||||
downloadFile(`${main?.url}`, `${main.names}`);
|
||||
} else {
|
||||
// const url = `${process.env.NEXT_PUBLIC_API}/media/view?id=${main?.id}&operation=file&type=video&resolution=${resolutionSelected}p`;
|
||||
// downloadFile(url, `${main.names}`);
|
||||
const url = `${process.env.NEXT_PUBLIC_API}/media/view?id=${main?.id}&operation=file&type=image&resolution=${imageSizeSelected}`;
|
||||
downloadFile(url, `${main.names}`);
|
||||
}
|
||||
}
|
||||
// } else if (type === "1" && resolutionSelected?.length > 0) {
|
||||
// if (isFromSPIT && main?.url?.includes("spit.humas")) {
|
||||
// downloadFile(`${main?.url}`, `${main.names}`);
|
||||
// } else {
|
||||
// const url = `${process.env.NEXT_PUBLIC_API}/media/view?id=${main?.id}&operation=file&type=video&resolution=${resolutionSelected}p`;
|
||||
// downloadFile(url, `${main.names}`);
|
||||
// }
|
||||
// } else if (type === "2" && imageSizeSelected?.length > 0) {
|
||||
// const url = `${process.env.NEXT_PUBLIC_API}/media/view?id=${main?.id}&operation=file&type=image&resolution=${imageSizeSelected}`;
|
||||
// downloadFile(url, `${main.names}`);
|
||||
// } else if (type === "3" || type === "4") {
|
||||
// downloadFile(`${main?.url}`, `${main.names}`);
|
||||
// }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const downloadFile = (fileUrl: string, name: string) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open("GET", fileUrl, true);
|
||||
xhr.responseType = "blob";
|
||||
|
||||
xhr.addEventListener("progress", (event) => {
|
||||
if (event.lengthComputable) {
|
||||
const percentCompleted = Math.round((event.loaded / event.total) * 100);
|
||||
setDownloadProgress(percentCompleted);
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener("readystatechange", () => {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
const contentType =
|
||||
xhr.getResponseHeader("content-type") || "application/octet-stream";
|
||||
const extension = contentType.split("/")[1];
|
||||
const filename = `${name}.${extension}`;
|
||||
|
||||
const blob = new Blob([xhr.response], {
|
||||
type: contentType,
|
||||
});
|
||||
const downloadUrl = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
|
||||
a.href = downloadUrl;
|
||||
a.download = filename;
|
||||
document.body.append(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
}
|
||||
});
|
||||
|
||||
xhr.onloadend = () => {
|
||||
setDownloadProgress(0);
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
const showInput = (e: any) => {
|
||||
console.log(document.querySelector(`#${e}`)?.classList);
|
||||
document.querySelector(`#${e}`)?.classList.toggle("none");
|
||||
setVisibleInput(visibleInput === e ? null : e);
|
||||
};
|
||||
|
||||
async function sendSuggestionParent() {
|
||||
if (message?.length > 3) {
|
||||
loading();
|
||||
const data = {
|
||||
mediaUploadId: slug?.split("-")?.[0],
|
||||
message,
|
||||
parentId: null,
|
||||
};
|
||||
|
||||
const response = await createPublicSuggestion(data);
|
||||
|
||||
console.log(response);
|
||||
setMessage("");
|
||||
|
||||
const responseGet = await getPublicSuggestionList(slug?.split("-")?.[0]);
|
||||
console.log(responseGet?.data?.data);
|
||||
setListSuggestion(responseGet?.data?.data);
|
||||
|
||||
// Hapus nilai semua input secara manual jika perlu
|
||||
const inputs = document.querySelectorAll("input");
|
||||
inputs.forEach((input) => {
|
||||
input.value = "";
|
||||
});
|
||||
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
async function sendSuggestionChild(parentId: any) {
|
||||
const inputElement = document.querySelector(
|
||||
`#input-comment-${parentId}`
|
||||
) as HTMLInputElement;
|
||||
|
||||
if (inputElement && inputElement.value.length > 3) {
|
||||
loading();
|
||||
const data = {
|
||||
mediaUploadId: slug?.split("-")?.[0],
|
||||
message: inputElement.value,
|
||||
parentId,
|
||||
};
|
||||
|
||||
console.log(data);
|
||||
const response = await createPublicSuggestion(data);
|
||||
console.log(response);
|
||||
const responseGet: any = await getPublicSuggestionList(
|
||||
slug?.split("-")?.[0]
|
||||
);
|
||||
console.log(responseGet?.data?.data);
|
||||
setListSuggestion(responseGet?.data?.data);
|
||||
|
||||
// Reset input field
|
||||
inputElement.value = "";
|
||||
|
||||
// document.querySelector("#comment-id-" + parentId)?.style.display = "none";
|
||||
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
const postData = () => {
|
||||
const checkMessage = checkMaliciousText(message);
|
||||
if (checkMessage == "") {
|
||||
if (Number(userRoleId) < 1 || userRoleId == undefined) {
|
||||
router.push("/auth");
|
||||
} else {
|
||||
sendSuggestionParent();
|
||||
}
|
||||
} else {
|
||||
warning(checkMessage);
|
||||
}
|
||||
};
|
||||
|
||||
const postDataChild = (id: any) => {
|
||||
const checkMessage = checkMaliciousText(message);
|
||||
if (checkMessage == "") {
|
||||
if (Number(userRoleId) < 1 || userRoleId == undefined) {
|
||||
router.push("/auth");
|
||||
} else {
|
||||
sendSuggestionChild(id);
|
||||
}
|
||||
} else {
|
||||
warning(checkMessage);
|
||||
}
|
||||
};
|
||||
|
||||
async function deleteDataSuggestion(dataId: any) {
|
||||
loading();
|
||||
const response = await deletePublicSuggestion(dataId);
|
||||
console.log(response);
|
||||
const responseGet = await getPublicSuggestionList(slug.split("-")?.[0]);
|
||||
console.log(responseGet?.data?.data);
|
||||
setListSuggestion(responseGet?.data?.data);
|
||||
close();
|
||||
}
|
||||
|
||||
const deleteData = (dataId: any) => {
|
||||
MySwal.fire({
|
||||
title: "Delete Comment",
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
cancelButtonColor: "#3085d6",
|
||||
confirmButtonColor: "#d33",
|
||||
confirmButtonText: "Delete",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
deleteDataSuggestion(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="min-h-screen px-4 md:px-24 py-4">
|
||||
<div className="rounded-md overflow-hidden md:flex">
|
||||
{/* Bagian Kiri */}
|
||||
<div className="md:w-3/4">
|
||||
{/* Gambar Besar */}
|
||||
<div className="relative">
|
||||
<Image
|
||||
width={1920}
|
||||
height={1080}
|
||||
src={
|
||||
detailDataImage?.files?.length > 0
|
||||
? detailDataImage.files[selectedImage]?.url
|
||||
: detailDataImage?.thumbnailLink
|
||||
}
|
||||
alt="Main"
|
||||
className="rounded-lg w-auto h-fit"
|
||||
/>
|
||||
<div className="absolute top-4 left-4"></div>
|
||||
</div>
|
||||
|
||||
{/* Gambar bawah Kecil */}
|
||||
<div className="py-4 flex flex-row gap-3">
|
||||
{detailDataImage?.files?.map((file: any, index: number) => (
|
||||
<a onClick={() => setSelectedImage(index)} key={file?.id}>
|
||||
<Image
|
||||
alt="imgae-small"
|
||||
width={1920}
|
||||
height={1080}
|
||||
src={file?.url}
|
||||
className="w-[120px] h-[90px] object-cover rounded-md cursor-pointer hover:ring-2 hover:ring-red-600"
|
||||
/>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Footer Informasi */}
|
||||
<div className="text-gray-500 flex flex-col lg:flex-row justify-between items-center border-t mt-4">
|
||||
<div className="flex flex-col lg:flex-row items-center mt-3 lg:justify-between">
|
||||
<p className="text-xs lg:text-sm">
|
||||
{t("by")}
|
||||
<span className="font-semibold text-black dark:text-white">
|
||||
{detailDataImage?.uploadedBy?.userLevel?.name}
|
||||
</span>
|
||||
</p>
|
||||
{/* <p className="text-xs lg:text-sm">
|
||||
| {t("updatedOn")}
|
||||
{detailDataImage?.updatedAt} WIB |
|
||||
</p> */}
|
||||
<p className="text-xs lg:text-sm">
|
||||
| {t("updatedOn")}
|
||||
{formatDateToIndonesian(
|
||||
new Date(detailDataImage?.updatedAt)
|
||||
)}{" "}
|
||||
{"WIB"}
|
||||
</p>
|
||||
<p className="text-xs lg:text-sm flex justify-center items-center">
|
||||
|
|
||||
<Icon icon="formkit:eye" width="15" height="15" />
|
||||
{detailDataImage?.clickCount}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<p className="flex text-end text-xs lg:text-sm font-semibold">
|
||||
{t("creator")}
|
||||
{detailDataImage?.creatorName}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Keterangan */}
|
||||
<div className="w-full">
|
||||
<h1 className="flex flex-row font-bold text-2xl my-8">
|
||||
{detailDataImage?.title}
|
||||
</h1>
|
||||
<div
|
||||
className="font-light text-justify mb-4"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: detailDataImage?.htmlDescription,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bagian Kanan */}
|
||||
<div className="md:w-1/4 p-4 bg-[#f7f7f7] h-fit rounded-lg mx-4">
|
||||
{isSaved ? (
|
||||
<a
|
||||
onClick={() => handleDeleteWishlist()}
|
||||
className="flex flex-col mb-3 items-center justify-center cursor-pointer"
|
||||
>
|
||||
<Icon icon="material-symbols:bookmark" width={40} />
|
||||
<p className="text-base lg:text-lg">Hapus</p>
|
||||
</a>
|
||||
) : (
|
||||
<a
|
||||
onClick={() => doBookmark()}
|
||||
className="flex flex-col mb-3 items-center justify-center cursor-pointer"
|
||||
>
|
||||
<Icon icon="material-symbols:bookmark-outline" width={40} />
|
||||
<p className="text-base lg:text-lg">Simpan</p>
|
||||
</a>
|
||||
)}
|
||||
|
||||
{/* garis */}
|
||||
<div className="border-t border-black my-4"></div>
|
||||
|
||||
<Link
|
||||
href={`/all/filter?title=polda&category=${detailDataImage?.category.id}`}
|
||||
className="bg-red-600 text-white text-xs font-bold px-3 py-3 my-3 flex justify-center items-center rounded"
|
||||
>
|
||||
{detailDataImage?.category?.name}
|
||||
</Link>
|
||||
|
||||
<div className="flex justify-center flex-wrap gap-2 mb-4">
|
||||
{detailDataImage?.tags?.split(",").map((tag: string) => (
|
||||
<a
|
||||
onClick={() => router.push(`/all/filter?tag=${tag}`)}
|
||||
key={tag}
|
||||
className="bg-gray-200 text-gray-700 text-xs px-3 py-1 rounded-full cursor-pointer hover:bg-gray-500"
|
||||
>
|
||||
{tag}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="border-t border-black my-4"></div>
|
||||
|
||||
{/* Opsi Ukuran Foto */}
|
||||
<h4 className="flex text-lg justify-center items-center font-semibold my-3">
|
||||
Opsi Ukuran Foto
|
||||
</h4>
|
||||
<div className="border-t border-black my-4"></div>
|
||||
|
||||
<div className="space-y-2">
|
||||
{sizes.map((size: any) => (
|
||||
<div className="flex flex-row justify-between">
|
||||
<div
|
||||
key={size.label}
|
||||
className="items-center flex flex-row gap-2 cursor-pointer"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="size"
|
||||
value={size.label}
|
||||
checked={selectedSize === size.label}
|
||||
onChange={() => setSelectedSize(size.label)}
|
||||
className="text-red-600 focus:ring-red-600"
|
||||
/>
|
||||
<div className="text-sm">{size.label}</div>
|
||||
</div>
|
||||
<div className="">
|
||||
<div className="text-sm">{size.value}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Download Semua */}
|
||||
<div className="mt-4">
|
||||
<label className="flex items-center space-x-2 text-sm">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="text-red-600 focus:ring-red-600"
|
||||
onChange={() => setIsDownloadAll(!isDownloadAll)}
|
||||
/>
|
||||
<span>Download Semua File?</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Tombol Download */}
|
||||
<button
|
||||
onClick={handleDownload}
|
||||
className="mt-4 bg-red-600 text-white w-full py-2 flex justify-center items-center gap-1 rounded-md text-sm hover:bg-red-700"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="white"
|
||||
d="m12 16l-5-5l1.4-1.45l2.6 2.6V4h2v8.15l2.6-2.6L17 11zm-6 4q-.825 0-1.412-.587T4 18v-3h2v3h12v-3h2v3q0 .825-.587 1.413T18 20z"
|
||||
/>
|
||||
</svg>
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full">
|
||||
{/* Comment */}
|
||||
<div className="flex flex-col mt-16 p-4 lg:p-10 bg-[#f7f7f7] dark:bg-slate-600">
|
||||
<div className="gap-5 flex flex-col px-4 lg:px-14">
|
||||
<p className="flex items-start text-lg">{t("comment")}</p>
|
||||
<Textarea
|
||||
placeholder={t("leaveComment")}
|
||||
className="flex w-full pb-12"
|
||||
onChange={getInputValue}
|
||||
/>
|
||||
<button
|
||||
onClick={() => postData()}
|
||||
className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1"
|
||||
>
|
||||
{t("send")}
|
||||
</button>
|
||||
<div className="border-b-2 border-slate-300 mt-4 w-full self-center"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{listSuggestion?.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={1080}
|
||||
height={1080}
|
||||
src={data?.suggestionFrom?.profilePictureUrl}
|
||||
className="h-12 lg:h-16 w-12 lg:w-16 mr-2"
|
||||
onError={addDefaultProfile}
|
||||
alt=""
|
||||
/>
|
||||
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
|
||||
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
|
||||
{Number(data.suggestionFrom?.roleId) == 2 ||
|
||||
Number(data.suggestionFrom?.roleId) == 3 ||
|
||||
Number(data.suggestionFrom?.roleId) == 4
|
||||
? "HUMAS POLRI"
|
||||
: data.suggestionFrom?.fullname}
|
||||
{getPublicLocaleTimestamp(new Date(data.createdAt))}
|
||||
</p>
|
||||
<p className="text-slate-500 text-[13px] lg:text-sm mb-4">
|
||||
{data?.message}
|
||||
</p>
|
||||
<div>
|
||||
<a
|
||||
style={
|
||||
Number(data.suggestionFrom?.id) == Number(userId)
|
||||
? {
|
||||
display: "none",
|
||||
}
|
||||
: {}
|
||||
}
|
||||
onClick={() => showInput(`comment-id-${data.id}`)}
|
||||
className="mr-2"
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("reply")}
|
||||
</small>
|
||||
</a>
|
||||
{Number(data.suggestionFrom?.id) == Number(userId) ||
|
||||
Number(userRoleId) == 2 ? (
|
||||
<a onClick={() => deleteData(data.id)}>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("delete")}
|
||||
</small>
|
||||
</a>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{visibleInput === `comment-id-${data.id}` && (
|
||||
<div
|
||||
id={`comment-id-${data.id}`}
|
||||
className="px-4 pl-[72px] lg:px-14 lg:pl-32 mt-2 "
|
||||
>
|
||||
<Textarea
|
||||
id={`input-comment-${data.id}`}
|
||||
className="p-4 focus:outline-none focus:border-sky-500"
|
||||
placeholder={t("enterReply")}
|
||||
/>
|
||||
<div className="flex flex-row gap-3">
|
||||
<a onClick={() => postDataChild(data.id)}>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 mt-2 cursor-pointer">
|
||||
{t("send")}
|
||||
</small>
|
||||
</a>
|
||||
<a onClick={() => showInput(`comment-id-${data.id}`)}>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg mt-2 w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("cancel")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</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-16 lg:pl-32">
|
||||
<Image
|
||||
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||
shimmer(700, 475)
|
||||
)}`}
|
||||
width={1080}
|
||||
height={1080}
|
||||
src={child1.suggestionFrom?.profilePictureUrl}
|
||||
onError={addDefaultProfile}
|
||||
alt=""
|
||||
className="h-10 lg:h-16 w-10 lg:w-16 mr-2"
|
||||
/>
|
||||
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
|
||||
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
|
||||
{" "}
|
||||
<b>
|
||||
{Number(child1.suggestionFrom?.roleId) == 2 ||
|
||||
Number(child1.suggestionFrom?.roleId) == 3 ||
|
||||
Number(child1.suggestionFrom?.roleId) == 4
|
||||
? "HUMAS POLRI"
|
||||
: child1.suggestionFrom?.fullname}
|
||||
</b>{" "}
|
||||
{getPublicLocaleTimestamp(
|
||||
new Date(child1.createdAt)
|
||||
)}
|
||||
</p>
|
||||
<p className="text-slate-500 text-[13px] lg:text-sm mb-4">
|
||||
{parse(String(child1?.message))}
|
||||
</p>
|
||||
<div>
|
||||
<a
|
||||
style={
|
||||
Number(child1.suggestionFrom?.id) ==
|
||||
Number(userId)
|
||||
? {
|
||||
display: "none",
|
||||
}
|
||||
: {}
|
||||
}
|
||||
onClick={() =>
|
||||
showInput(`comment-id-${child1.id}`)
|
||||
}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("reply")}
|
||||
</small>
|
||||
</a>
|
||||
<a
|
||||
style={
|
||||
Number(child1.suggestionFrom?.id) ==
|
||||
Number(userId)
|
||||
? {}
|
||||
: {
|
||||
display: "none",
|
||||
}
|
||||
}
|
||||
onClick={() => deleteData(child1.id)}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("delete")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{visibleInput === `comment-id-${child1.id}` && (
|
||||
<div
|
||||
id={`comment-id-${child1.id}`}
|
||||
className="px-4 lg:px-14 pl-28 lg:pl-[200px]"
|
||||
>
|
||||
<Textarea
|
||||
name=""
|
||||
className="mt-2 "
|
||||
id={`input-comment-${child1.id}`}
|
||||
placeholder={t("enterReply")}
|
||||
/>
|
||||
<div className="flex flex-row mt-2 gap-3">
|
||||
<a onClick={() => postDataChild(child1.id)}>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("send")}
|
||||
</small>
|
||||
</a>
|
||||
<a
|
||||
onClick={() =>
|
||||
showInput(`comment-id-${child1.id}`)
|
||||
}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("cancel")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{child1.children.length > 0
|
||||
? child1.children?.map((child2: any) => (
|
||||
<div className="">
|
||||
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-28 lg:pl-48">
|
||||
<Image
|
||||
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||
shimmer(700, 475)
|
||||
)}`}
|
||||
width={1080}
|
||||
height={1080}
|
||||
src={
|
||||
child2.suggestionFrom?.profilePictureUrl
|
||||
}
|
||||
className="h-9 lg:h-16 w-9 lg:w-16 mr-2"
|
||||
onError={addDefaultProfile}
|
||||
alt=""
|
||||
/>
|
||||
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
|
||||
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
|
||||
{" "}
|
||||
<b>
|
||||
{Number(
|
||||
child2.suggestionFrom?.roleId
|
||||
) == 2 ||
|
||||
Number(child2.suggestionFrom?.roleId) ==
|
||||
3 ||
|
||||
Number(child2.suggestionFrom?.roleId) ==
|
||||
4
|
||||
? "HUMAS POLRI"
|
||||
: child2.suggestionFrom?.fullname}
|
||||
</b>{" "}
|
||||
{getPublicLocaleTimestamp(
|
||||
new Date(child2.createdAt)
|
||||
)}
|
||||
</p>
|
||||
<p className="text-slate-500 text-sm mb-4">
|
||||
{parse(String(child2?.message))}
|
||||
</p>
|
||||
<div>
|
||||
<a
|
||||
style={
|
||||
Number(child2.suggestionFrom?.id) ==
|
||||
Number(userId)
|
||||
? {
|
||||
display: "none",
|
||||
}
|
||||
: {}
|
||||
}
|
||||
onClick={() =>
|
||||
showInput(`comment-id-${child2.id}`)
|
||||
}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("reply")}
|
||||
</small>
|
||||
</a>
|
||||
<a
|
||||
style={
|
||||
Number(child2.suggestionFrom?.id) ==
|
||||
Number(userId)
|
||||
? {}
|
||||
: {
|
||||
display: "none",
|
||||
}
|
||||
}
|
||||
onClick={() => deleteData(child2.id)}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("delete")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{visibleInput === `comment-id-${child2.id}` && (
|
||||
<div
|
||||
id={`comment-id-${child2.id}`}
|
||||
className="px-4 lg:px-14 pl-40 lg:pl-[265px]"
|
||||
>
|
||||
<Textarea
|
||||
name=""
|
||||
id={`input-comment-${child2.id}`}
|
||||
className="my-2"
|
||||
placeholder="Masukkan balasan anda"
|
||||
/>
|
||||
<div className="flex flex-row gap-3">
|
||||
<a
|
||||
onClick={() => postDataChild(child2.id)}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("send")}
|
||||
</small>
|
||||
</a>
|
||||
<a
|
||||
onClick={() =>
|
||||
showInput(`comment-id-${child2.id}`)
|
||||
}
|
||||
>
|
||||
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">
|
||||
{t("cancel")}
|
||||
</small>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
: ""}
|
||||
</div>
|
||||
))
|
||||
: ""}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Konten Serupa */}
|
||||
{/* <div className="">
|
||||
<NewContent group="mabes" type={"similar"} />
|
||||
</div> */}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailInfo;
|
||||
export async function generateMetadata({ params }: any): Promise<Metadata> {
|
||||
const slug = String(params?.slug);
|
||||
const res = await getDetailMetaData(String(slug));
|
||||
const image = res?.data?.data;
|
||||
// console.log("image", image);
|
||||
return {
|
||||
title: image.title,
|
||||
description: image.description,
|
||||
openGraph: {
|
||||
title: image?.title,
|
||||
description: image?.description,
|
||||
images: [`${image?.thumbnailLink}`],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default async function DetailInfo({ params }: Props) {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<DetailImage />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -677,7 +677,14 @@ const FilterPage = () => {
|
|||
className="hover:scale-105 transition-transform duration-300"
|
||||
>
|
||||
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
||||
<Link href={`/image/detail/${image?.slug}`}>
|
||||
<div
|
||||
// href={`/image/detail/${image?.slug}`}
|
||||
onClick={() =>
|
||||
router.push(
|
||||
prefixPath + `/image/detail/${image?.slug}`
|
||||
)
|
||||
}
|
||||
>
|
||||
{/* <img src={image?.thumbnailLink} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg" /> */}
|
||||
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg">
|
||||
<ImageBlurry
|
||||
|
|
@ -709,7 +716,7 @@ const FilterPage = () => {
|
|||
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">
|
||||
{image?.title}
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import ContentCategory from "@/components/landing-page/content-category";
|
||||
import HeaderBanner from "@/components/landing-page/header-banner";
|
||||
import NewContent from "@/components/landing-page/new-content";
|
||||
import WelcomePolda from "@/components/landing-page/welcome-polda";
|
||||
import React from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
import NavbarKaltara from "@/components/landing-page/landing-polda-kaltara/navbar-polda-kaltara";
|
||||
import HeaderBannerKaltara from "@/components/landing-page/landing-polda-kaltara/header-banner-kaltara";
|
||||
import SearchSectionKaltara from "@/components/landing-page/landing-polda-kaltara/search-section-kaltara";
|
||||
import LatestContentKaltara from "@/components/landing-page/landing-polda-kaltara/latest-content-kaltara";
|
||||
import ContactUsKaltara from "@/components/landing-page/landing-polda-kaltara/contact-us-kaltara";
|
||||
import NewsTickerKaltara from "../../tbnews/[polda_name]/components/news-tickers-kaltara";
|
||||
import ContentCategoryKaltara from "@/components/landing-page/landing-polda-kaltara/content-category-kaltara";
|
||||
import HeroNew from "@/components/landing-page/hero-new";
|
||||
import Navbar from "@/components/landing-page/navbar";
|
||||
import SearchSection from "@/components/landing-page/search-section";
|
||||
import Footer from "@/components/landing-page/footer";
|
||||
import SearchSectionPolda from "@/components/landing-page/search-section-polda";
|
||||
import HeroNewPolda from "@/components/landing-page/hero-new-polda";
|
||||
|
||||
const page = () => {
|
||||
const params = useParams();
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ const DetailVideo = () => {
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
|
||||
<path fill="white" d="m12 16l-5-5l1.4-1.45l2.6 2.6V4h2v8.15l2.6-2.6L17 11zm-6 4q-.825 0-1.412-.587T4 18v-3h2v3h12v-3h2v3q0 .825-.587 1.413T18 20z" />
|
||||
</svg>
|
||||
Download
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -333,7 +333,7 @@ const DetailVideo = () => {
|
|||
</div>
|
||||
|
||||
{/* Konten Serupa */}
|
||||
<div className="">
|
||||
<div className="px-4 lg:px-24">
|
||||
<NewContent group="polda" type={"similar"} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -692,7 +692,10 @@ const FilterPage = () => {
|
|||
className="hover:scale-110 transition-transform duration-300"
|
||||
>
|
||||
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
||||
<Link href={`/video/detail/${video?.slug}`}>
|
||||
<div
|
||||
// href={`/video/detail/${video?.slug}`}
|
||||
onClick={() => router.push(prefixPath + `/video/detail/${video?.slug}`)}
|
||||
>
|
||||
{/* <img src={video?.thumbnailLink} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" /> */}
|
||||
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg">
|
||||
<ImageBlurry
|
||||
|
|
@ -720,7 +723,7 @@ const FilterPage = () => {
|
|||
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">
|
||||
{video?.title}
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ const NewContent = (props: { group: string; type: string }) => {
|
|||
)
|
||||
) : selectedTab == "audio" ? (
|
||||
newContent?.length > 0 ? (
|
||||
<Carousel setApi={setApi} className="w-full max-w-7xl mx-auto">
|
||||
<Carousel setApi={setApi} className="w-full mx-auto">
|
||||
<CarouselContent>
|
||||
{newContent?.map((audio: any) => (
|
||||
<CarouselItem key={audio?.id} className="md:basis-1/2 lg:basis-1/3">
|
||||
|
|
@ -309,7 +309,7 @@ const NewContent = (props: { group: string; type: string }) => {
|
|||
</p>
|
||||
)
|
||||
) : newContent.length > 0 ? (
|
||||
<Carousel setApi={setApi} className="w-full max-w-7xl mx-auto">
|
||||
<Carousel setApi={setApi} className="w-full mx-auto">
|
||||
<CarouselContent>
|
||||
{newContent?.map((text: any) => (
|
||||
<CarouselItem key={text?.id} className="md:basis-1/2 lg:basis-1/3">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@
|
|||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
*CYGWIN*|*MINGW*|*MSYS*)
|
||||
if command -v cygpath > /dev/null 2>&1; then
|
||||
basedir=`cygpath -w "$basedir"`
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@
|
|||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
|
||||
*CYGWIN*|*MINGW*|*MSYS*)
|
||||
if command -v cygpath > /dev/null 2>&1; then
|
||||
basedir=`cygpath -w "$basedir"`
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
|
|
|
|||
Loading…
Reference in New Issue