feat: comment section in detail image

This commit is contained in:
sabdayagra 2025-01-20 21:51:01 +07:00
parent 50ebdb2429
commit 9266b1924d
2 changed files with 261 additions and 61 deletions

View File

@ -8,15 +8,19 @@ import NewContent from "@/components/landing-page/new-content";
import { useToast } from "@/components/ui/use-toast"; import { useToast } from "@/components/ui/use-toast";
import { getCookiesDecrypt } from "@/lib/utils"; import { getCookiesDecrypt } from "@/lib/utils";
import { close, error, loading, successCallback, warning } from "@/config/swal"; import { close, error, loading, successCallback, warning } from "@/config/swal";
import { checkWishlistStatus, createPublicSuggestion, deleteWishlist, getDetail, getPublicSuggestionList, saveWishlist } from "@/service/landing/landing"; import { checkWishlistStatus, createPublicSuggestion, deletePublicSuggestion, deleteWishlist, getDetail, getPublicSuggestionList, saveWishlist } from "@/service/landing/landing";
import { Link, useRouter } from "@/i18n/routing"; import { Link, useRouter } from "@/i18n/routing";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking"; import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking";
import { checkMaliciousText } from "@/utils/globals"; import { checkMaliciousText, getPublicLocaleTimestamp } from "@/utils/globals";
import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2";
import parse from "html-react-parser";
const DetailInfo = () => { const DetailInfo = () => {
const MySwal = withReactContent(Swal);
const [selectedSize, setSelectedSize] = useState<string>("L"); const [selectedSize, setSelectedSize] = useState<string>("L");
const [selectedTab, setSelectedTab] = useState("video"); const [selectedTab, setSelectedTab] = useState("video");
const router = useRouter(); const router = useRouter();
@ -40,12 +44,10 @@ const DetailInfo = () => {
const [emailShareInput, setEmailShareInput] = useState<any>(); const [emailShareInput, setEmailShareInput] = useState<any>();
const [emailMessageInput, setEmailMessageInput] = useState(); const [emailMessageInput, setEmailMessageInput] = useState();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const id = searchParams?.get("id");
const [width, setWidth] = useState<any>(); const [width, setWidth] = useState<any>();
const userRoleId = getCookiesDecrypt("urie"); const userRoleId = getCookiesDecrypt("urie");
const [message, setMessage] = useState(""); const [message, setMessage] = useState("");
const [listSuggestion, setListSuggestion] = useState(); const [listSuggestion, setListSuggestion] = useState<any>();
let typeString = "image"; let typeString = "image";
@ -57,9 +59,12 @@ const DetailInfo = () => {
const initFetch = async () => { const initFetch = async () => {
const response = await getDetail(String(slug)); const response = await getDetail(String(slug));
console.log("detailImage", response); console.log("detailImage", response);
const responseGet = await getPublicSuggestionList(slug?.split("-")?.[0]);
setIsFromSPIT(response?.data?.data?.isFromSPIT); setIsFromSPIT(response?.data?.data?.isFromSPIT);
setWidth(window.innerWidth); setWidth(window.innerWidth);
setContent(response?.data.data); setContent(response?.data.data);
setListSuggestion(responseGet.data?.data);
setMain({ setMain({
id: response?.data?.data?.files[0]?.id, id: response?.data?.data?.files[0]?.id,
type: response?.data?.data?.fileType.name, type: response?.data?.data?.fileType.name,
@ -259,7 +264,7 @@ const DetailInfo = () => {
router.push("/auth/login"); router.push("/auth/login");
} else { } else {
const data = { const data = {
mediaUploadId: id?.split("-")?.[0], mediaUploadId: slug?.split("-")?.[0],
email: emailShareList || [emailShareInput], email: emailShareList || [emailShareInput],
message: emailMessageInput, message: emailMessageInput,
url: window.location.href, url: window.location.href,
@ -291,6 +296,15 @@ const DetailInfo = () => {
return false; return false;
}; };
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("comment-hidden");
};
const getInputValue = (e: any) => { const getInputValue = (e: any) => {
const message = e.target.value; const message = e.target.value;
console.log(message); console.log(message);
@ -301,7 +315,7 @@ const DetailInfo = () => {
if (message?.length > 3) { if (message?.length > 3) {
loading(); loading();
const data = { const data = {
mediaUploadId: id?.split("-")?.[0], mediaUploadId: slug?.split("-")?.[0],
message, message,
parentId: null, parentId: null,
}; };
@ -310,44 +324,53 @@ const DetailInfo = () => {
console.log(response); console.log(response);
setMessage(""); setMessage("");
const responseGet = await getPublicSuggestionList(id?.split("-")?.[0]);
const responseGet = await getPublicSuggestionList(slug?.split("-")?.[0]);
console.log(responseGet?.data?.data); console.log(responseGet?.data?.data);
setListSuggestion(responseGet?.data?.data); setListSuggestion(responseGet?.data?.data);
$(":input").val("");
// Hapus nilai semua input secara manual jika perlu
const inputs = document.querySelectorAll("input");
inputs.forEach((input) => {
input.value = "";
});
close(); close();
} }
} }
// async function sendSuggestionChild(parentId: any) { async function sendSuggestionChild(parentId: any) {
// const inputMsg = document.querySelectorAll(`#input-comment-${parentId}`)[0] const inputElement = document.querySelector(`#input-comment-${parentId}`) as HTMLInputElement;
// .value;
// if (inputMsg?.length > 3) { if (inputElement && inputElement.value.length > 3) {
// loading(); loading();
// const data = { const data = {
// mediaUploadId: id?.split("-")?.[0], mediaUploadId: slug?.split("-")?.[0],
// message: inputMsg, message: inputElement.value,
// parentId, parentId,
// }; };
// console.log(data); console.log(data);
// const response = await createPublicSuggestion(data); const response = await createPublicSuggestion(data);
// console.log(response); console.log(response);
// const responseGet: any = await getPublicSuggestionList(id?.split("-")?.[0]); const responseGet: any = await getPublicSuggestionList(slug?.split("-")?.[0]);
// console.log(responseGet.data?.data); console.log(responseGet.data?.data);
// setListSuggestion(responseGet.data?.data); setListSuggestion(responseGet.data?.data);
// // $(":input").val("");
// document.querySelectorAll(`#input-comment-${parentId}`)[0].value = ""; // Reset input field
// // document.querySelectorAll("#comment-id-" + parentId)[0].style.display = "none"; inputElement.value = "";
// close();
// } // document.querySelector("#comment-id-" + parentId)?.style.display = "none";
// }
close();
}
}
const postData = () => { const postData = () => {
const checkMessage = checkMaliciousText(message); const checkMessage = checkMaliciousText(message);
if (checkMessage == "") { if (checkMessage == "") {
if (Number(userRoleId) < 1 || userRoleId == undefined) { if (Number(userRoleId) < 1 || userRoleId == undefined) {
router.push("/auth/login"); router.push("/auth");
} else { } else {
sendSuggestionParent(); sendSuggestionParent();
} }
@ -356,19 +379,44 @@ const DetailInfo = () => {
} }
}; };
// const postDataChild = (id: any) => { const postDataChild = (id: any) => {
// const checkMessage = checkMaliciousText(message); const checkMessage = checkMaliciousText(message);
// if (checkMessage == "") { if (checkMessage == "") {
// if (Number(userRoleId) < 1 || userRoleId == undefined) { if (Number(userRoleId) < 1 || userRoleId == undefined) {
// router.push("/auth/login"); router.push("/auth/login");
// } } else {
// else { sendSuggestionChild(id);
// sendSuggestionChild(id); }
// } } else {
// } else { warning(checkMessage);
// 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);
}
});
};
return ( return (
<> <>
@ -514,17 +562,164 @@ const DetailInfo = () => {
<div className="flex flex-col my-16 p-10 bg-[#f7f7f7]"> <div className="flex flex-col my-16 p-10 bg-[#f7f7f7]">
<div className="gap-5 flex flex-col px-4 lg:px-14"> <div className="gap-5 flex flex-col px-4 lg:px-14">
<p className="flex items-start text-lg">Berikan Komentar</p> <p className="flex items-start text-lg">Berikan Komentar</p>
<Textarea placeholder="Type your comments here." className="flex w-full" onChange={getInputValue} /> <Textarea placeholder="Type your comments here." className="flex w-full py-8" onChange={getInputValue} />
<button className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1">Kirim</button> <button onClick={() => postData()} className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1">
Kirim
</button>
</div> </div>
<div className="border-b-2 border-black mt-4"></div>
<div className="flex flex-row">
<img src="/assets/avatar-profile.png" alt="avatar" />
<div className="bg-white border border-black ">
<div className="border-b-2 border-slate-300 mt-4 w-auto"></div>
{listSuggestion?.map((data: any) => (
<div className="flex flex-col overflow-y-auto">
<div className="flex flex-row mt-2 px-4 lg:px-14">
<img src={data?.suggestionFrom?.profilePictureUrl} className="h-16 w-16 mr-2" onError={addDefaultProfile} alt="" />
<div className="border border-slate-300 w-full p-4 bg-white gap-1">
<p className="text-slate-500 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-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-4 py-1 cursor-pointer">Balas</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-4 py-1 cursor-pointer">Hapus</small>
</a>
) : (
""
)}
</div> </div>
</div> </div>
</div> </div>
<div id={`comment-id-${data.id}`} className="px-4 lg:px-28 mt-2">
<Textarea id={`input-comment-${data.id}`} className="p-4 focus:outline-none focus:border-sky-500" placeholder="Masukkan balasan anda" />
<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-4 py-1 mt-2 cursor-pointer">Kirim</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-4 py-1 cursor-pointer">Batal</small>
</a>
</div>
</div>
{data.children.length > 0
? data.children?.map((child1: any) => (
<div className="flex flex-row mt-2">
<img src={child1.suggestionFrom?.profilePictureUrl} onError={addDefaultProfile} alt="" className="h-16 w-16 mr-2" />
<div className="border border-slate-300 w-full p-4 bg-white gap-1">
<p className="text-slate-500 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-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-4 py-1 cursor-pointer">Balas</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-4 py-1 cursor-pointer">Hapus</small>
</a>
</div>
</div>
<div id={`comment-id-${child1.id}`}>
<Textarea name="" id={`input-comment-${child1.id}`} placeholder="Masukkan balasan anda" />
<a onClick={() => postDataChild(child1.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1 cursor-pointer">Kirim</small>
</a>
<a onClick={() => showInput(`comment-id-${child1.id}`)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1 cursor-pointer">Batal</small>
</a>
</div>
{child1.children.length > 0
? child1.children?.map((child2: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2">
<img src={child2.suggestionFrom?.profilePictureUrl} className="h-16 w-16 mr-2" onError={addDefaultProfile} alt="" />
<div className="border border-slate-300 w-full p-4 bg-white gap-1">
<p className="text-slate-500 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-4 py-1 cursor-pointer">Balas</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-4 py-1 cursor-pointer">Hapus</small>
</a>
</div>
</div>
<div id={`comment-id-${child2.id}`}>
<Textarea name="" id={`input-comment-${child2.id}`} placeholder="Masukkan balasan anda" />
<a onClick={() => postDataChild(child2.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1 cursor-pointer">Kirim</small>
</a>
<a onClick={() => showInput(`comment-id-${child2.id}`)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1 cursor-pointer">Batal</small>
</a>
</div>
</div>
</div>
))
: ""}
</div>
))
: ""}
</div>
))}
</div>
{/* Konten Serupa */} {/* Konten Serupa */}
<div className=""> <div className="">

View File

@ -139,9 +139,12 @@ export async function saveWishlist(data: { mediaUploadId: string }) {
return httpPostInterceptor(url, data); return httpPostInterceptor(url, data);
} }
export async function getPublicSuggestionList(id: any) { export async function getPublicSuggestionList(slug: any) {
const url = `media/public/suggestion?mediaId=${id}`; const url = `media/public/suggestion?mediaId=${slug}`;
return httpGetInterceptor(url); const headers = {
"content-Type": "application/json",
};
return httpGet(url, headers);
} }
export async function getUserNotifications(page = 0, typeId: any) { export async function getUserNotifications(page = 0, typeId: any) {
@ -167,13 +170,15 @@ export async function saveUserReports(data: any) {
export async function listCarousel() { export async function listCarousel() {
const url = "/media/public/banner"; const url = "/media/public/banner";
return httpGetInterceptor(url) return httpGetInterceptor(url);
} }
export async function createPublicSuggestion(data: any) { export async function createPublicSuggestion(data: any) {
const url = 'media/public/suggestion'; const url = "media/public/suggestion";
const header = { return httpPostInterceptor(url, data);
"content-Type": "application/json", }
};
return httpGet( url, data ); export async function deletePublicSuggestion(slug: any) {
const url = `media/public/suggestion?id=${slug}`;
return httpDeleteInterceptor( url );
} }