"use client"; import React, { ChangeEvent, useEffect, useRef, useState } from "react"; import { useForm, Controller } from "react-hook-form"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Card } from "@/components/ui/card"; import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; import { useParams, useRouter } from "next/navigation"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Checkbox } from "@/components/ui/checkbox"; import Cookies from "js-cookie"; import { createMedia, getArticleDetail, getTagsBySubCategoryId, listEnableCategory, publishMedia, rejectFiles, submitApproval, } from "@/service/content/content"; import { Badge } from "@/components/ui/badge"; import { Swiper, SwiperSlide } from "swiper/react"; import "swiper/css"; import "swiper/css/free-mode"; import "swiper/css/navigation"; import "swiper/css/pagination"; import "swiper/css/thumbs"; import "swiper/css"; import "swiper/css/navigation"; import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; import { DialogHeader, DialogFooter, Dialog, DialogContent, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Textarea } from "@/components/ui/textarea"; import { close, loading, successCallback } from "@/config/swal"; import { getCookiesDecrypt } from "@/lib/utils"; import { Icon } from "@iconify/react/dist/iconify.js"; import { error } from "@/lib/swal"; import dynamic from "next/dynamic"; import SuggestionModal from "@/components/modal/suggestions-modal"; import { formatDateToIndonesian } from "@/utils/globals"; import ApprovalHistoryModal from "@/components/modal/approval-history-modal"; import { detailMedia, getDataApprovalByMediaUpload, } from "@/service/curated-content/curated-content"; import { UnitMapping } from "../unit-mapping"; const imageSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), description: z .string() .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), creatorName: z.string().min(1, { message: "Creator diperlukan" }), // tags: z.string().min(1, { message: "Judul diperlukan" }), }); type Category = { id: string; name: string; }; type FileType = { id: number; url: string; thumbnailFileUrl: string; fileName: string; // New API fields articleId?: number; filePath?: string; fileUrl?: string; fileThumbnail?: string | null; fileAlt?: string; widthPixel?: number | null; heightPixel?: number | null; size?: string; downloadCount?: number; createdById?: number; statusId?: number; isPublish?: boolean; publishedAt?: string | null; isActive?: boolean; createdAt?: string; updatedAt?: string; }; type Detail = { id: number; title: string; description: string; htmlDescription: string; slug: string; categoryId: number; categoryName: string; typeId: number; tags: string; thumbnailUrl: string; pageUrl: string | null; createdById: number; createdByName: string; shareCount: number; viewCount: number; commentCount: number; aiArticleId: number | null; oldId: number; statusId: number; isBanner: boolean; isPublish: boolean; publishedAt: string | null; isActive: boolean; createdAt: string; updatedAt: string; files: FileType[] | null; categories: { id: number; title: string; description: string; thumbnailUrl: string; slug: string | null; tags: string[]; thumbnailPath: string | null; parentId: number; oldCategoryId: number | null; createdById: number; statusId: number; isPublish: boolean; publishedAt: string | null; isEnabled: boolean | null; isActive: boolean; createdAt: string; updatedAt: string; }[]; // Legacy fields for backward compatibility category?: { id: number; name: string; }; creatorName?: string; thumbnailLink?: string; statusName?: string; needApprovalFromLevel?: number; uploadedById?: number; }; const ViewEditor = dynamic( () => { return import("@/components/editor/view-editor"); }, { ssr: false } ); export default function FormImageDetail() { const MySwal = withReactContent(Swal); const router = useRouter(); const userId = getCookiesDecrypt("uie"); const userLevelId = getCookiesDecrypt("ulie"); const userLevelName = Cookies.get("state"); const roleId = getCookiesDecrypt("urie"); console.log("LALALALA", userLevelName); const [modalOpen, setModalOpen] = useState(false); const { id } = useParams() as { id: string }; console.log("IDIDIDIDI", id); const editor = useRef(null); type ImageSchema = z.infer; const [selectedFiles, setSelectedFiles] = useState([]); const taskId = Cookies.get("taskId"); const scheduleId = Cookies.get("scheduleId"); const scheduleType = Cookies.get("scheduleType"); const [status, setStatus] = useState(""); const [categories, setCategories] = useState([]); const [selectedCategory, setSelectedCategory] = useState(); const [tags, setTags] = useState([]); const [detail, setDetail] = useState(); const [refresh, setRefresh] = useState(false); const [selectedPublishers, setSelectedPublishers] = useState([]); const [description, setDescription] = useState(""); const [main, setMain] = useState([]); const [filePlacements, setFilePlacements] = useState([]); const [detailThumb, setDetailThumb] = useState([]); const [thumbsSwiper, setThumbsSwiper] = useState(null); const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); const [approval, setApproval] = useState(); const [selectedTarget, setSelectedTarget] = useState(""); const [files, setFiles] = useState([]); const [rejectedFiles, setRejectedFiles] = useState([]); const [wilayahPublish, setWilayahPublish] = React.useState({ semua: false, nasional: false, polda: false, polres: false, satker: false, international: false, }); const [selectedPolda, setSelectedPolda] = React.useState([]); let fileTypeId = "1"; const { control, handleSubmit, setValue, formState: { errors }, } = useForm({ resolver: zodResolver(imageSchema), }); useEffect(() => { if ( userLevelId != undefined && roleId != undefined && userLevelId == "216" && roleId == "3" ) { setIsUserMabesApprover(true); } }, [userLevelId, roleId]); const handleCheckboxChange = (id: number) => { setSelectedPublishers((prev) => prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id] ); }; useEffect(() => { async function initState() { getCategories(); } initState(); }, []); const getCategories = async () => { try { const category = await listEnableCategory(fileTypeId); const resCategory: Category[] = category?.data; setCategories(resCategory); console.log("data category", resCategory); if (scheduleId && scheduleType === "3") { const findCategory = resCategory?.find((o) => o.name.toLowerCase().includes("pers rilis") ); if (findCategory) { // setValue("categoryId", findCategory.id); setSelectedCategory(findCategory.id); // Set the selected category const response = await getTagsBySubCategoryId(findCategory.id); setTags(response?.data); } } } catch (error) { console.error("Failed to fetch categories:", error); } }; const setupPlacementCheck = (length: number) => { const temp = []; for (let i = 0; i < length; i++) { temp.push([]); } setFilePlacements(temp); }; // useEffect(() => { // async function initState() { // if (id) { // const response = await detailMedia(id); // const details = response?.data; // console.log("detail", details); // setFiles(details?.files); // setDetail(details); // setMain({ // type: details?.fileType.name, // url: details?.files[0]?.url, // names: details?.files[0]?.fileName, // format: details?.files[0]?.format, // }); // setupPlacementCheck(details?.files?.length); // if (details.publishedForObject) { // const publisherIds = details.publishedForObject.map( // (obj: any) => obj.id // ); // setSelectedPublishers(publisherIds); // } // // Set the selected target to the category ID from details // setSelectedTarget(String(details.category.id)); // const filesData = details.files || []; // const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) => // file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" // ); // setDetailThumb(fileUrls); // const approvals = await getDataApprovalByMediaUpload(details?.id); // setApproval(approvals?.data); // } // } // initState(); // }, [refresh, setValue]); useEffect(() => { async function initState() { if (id) { try { const response = await getArticleDetail(Number(id)); const details = response?.data?.data; console.log("detail", details); // Map the new API response to the expected format const mappedDetail: Detail = { ...details, // Map legacy fields for backward compatibility category: details.categories && details.categories.length > 0 ? { id: details.categories[0].id, name: details.categories[0].title } : undefined, creatorName: details.createdByName, thumbnailLink: details.thumbnailUrl, statusName: getStatusName(details.statusId), needApprovalFromLevel: 0, // This might need to be updated based on your business logic uploadedById: details.createdById, files: details.files || [] }; // Map files from new API structure to expected format const mappedFiles = (mappedDetail.files || []).map((file: any) => ({ id: file.id, url: file.fileUrl || file.url, thumbnailFileUrl: file.fileThumbnail || file.thumbnailFileUrl || file.fileUrl, fileName: file.fileName || file.fileName, // Keep original API fields for reference ...file })); setFiles(mappedFiles); setDetail(mappedDetail); if (mappedFiles && mappedFiles.length > 0) { setMain({ type: "image", // Default type for articles url: mappedFiles[0]?.url || mappedDetail.thumbnailUrl, names: mappedFiles[0]?.fileName || "image", format: getFileExtension(mappedFiles[0]?.fileName || "jpg"), }); setupPlacementCheck(mappedFiles.length); } // Set the selected target to the category ID from details setSelectedTarget(String(mappedDetail.categoryId)); const fileUrls = mappedFiles.map((file: any) => file.thumbnailFileUrl || file.url || mappedDetail.thumbnailUrl || "default-image.jpg" ); setDetailThumb(fileUrls); // Note: You might need to update this API call as well const approvals = await getDataApprovalByMediaUpload(mappedDetail.id); setApproval(approvals?.data?.data); } catch (error) { console.error("Error fetching article detail:", error); } } } initState(); }, [refresh, setValue]); // Helper function to get status name from status ID const getStatusName = (statusId: number): string => { const statusMap: { [key: number]: string } = { 1: "Menunggu Review", 2: "Diterima", 3: "Minta Update", 4: "Ditolak" }; return statusMap[statusId] || "Unknown"; }; // Helper function to get file extension const getFileExtension = (filename: string): string => { const ext = filename.split('.').pop()?.toLowerCase(); return ext || 'jpg'; }; const actionApproval = (e: string) => { const temp = []; for (const element of detail.files) { temp.push([]); } setFilePlacements(temp); setStatus(e); setFiles(detail.files); setDescription(""); setModalOpen(true); }; const submit = async () => { if ( (description?.length > 1 && Number(status) == 3) || Number(status) == 2 || Number(status) == 4 ) { save(); // MySwal.fire({ // title: "Simpan Approval", // text: "", // icon: "warning", // showCancelButton: true, // cancelButtonColor: "#d33", // confirmButtonColor: "#3085d6", // confirmButtonText: "Simpan", // }).then((result) => { // if (result.isConfirmed) { // save(); // } // }); } }; const getPlacement = () => { console.log("getPlaa", filePlacements); const temp = []; for (let i = 0; i < filePlacements?.length; i++) { if (filePlacements[i].length !== 0) { const now = filePlacements[i].filter((a) => a !== "all"); const data = { mediaFileId: files[i].id, placements: now.join(",") }; temp.push(data); } } return temp; }; async function save() { const data = { action: status == "2" ? "approve" : status == "3" ? "revision" : "reject", message: description, }; setModalOpen(false); loading(); const response = await submitApproval(id, data); if (response?.error) { error(response.message); return false; } close(); submitApprovalSuccesss(); return false; } const setupPlacement = ( index: number, placement: string, checked: boolean ) => { let temp = [...filePlacements]; if (checked) { if (placement === "all") { temp[index] = ["all", "mabes", "polda", "international"]; } else { const now = temp[index]; now.push(placement); if (now.length === 3 && !now.includes("all")) { now.push("all"); } temp[index] = now; } } else { if (placement === "all") { temp[index] = []; } else { const now = temp[index].filter((a) => a !== placement); console.log("now", now); temp[index] = now; if (now.length === 3 && now.includes("all")) { const newData = now.filter((b) => b !== "all"); temp[index] = newData; } } } setFilePlacements(temp); }; function handleDeleteFileApproval(id: number) { const selectedFiles = files.filter((file) => file.id != id); setFiles(selectedFiles); const rejects = rejectedFiles; rejects.push(id); setRejectedFiles(rejects); } const handleMain = ( type: string, url: string, names: string, format: string ) => { console.log("Test 3 :", type, url, names, format); setMain({ type, url, names, format, }); return false; }; const submitApprovalSuccesss = () => { MySwal.fire({ title: "Sukses", text: "Data berhasil disimpan.", icon: "success", confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then((result) => { if (result.isConfirmed) { router.push("/admin/content/image"); } }); }; const publishToMabes = async () => { const res = await publishMedia(id); successCallback(); }; const [portraitMap, setPortraitMap] = useState({}); const handleImageLoad = (e: any, index: number) => { const { naturalWidth, naturalHeight } = e.target; const isPortrait = naturalHeight > naturalWidth; setPortraitMap((prev: any) => ({ ...prev, [index]: isPortrait, })); }; useEffect(() => { console.log("portrai", portraitMap); }, [portraitMap]); return (
{detail !== undefined ? (

Form Image

{/* Input Title */}
( )} /> {errors.title?.message && (

{errors.title.message}

)}
( )} /> {errors.description?.message && (

{errors.description.message}

)}
{detailThumb?.map((data: any, index: number) => ( {`Image ))}
{detailThumb?.map((data: any, index: number) => ( {`Thumbnail ))}
( )} /> {errors.creatorName?.message && (

{errors.creatorName.message}

)}
Thumbnail Gambar Utama
{detail?.tags ?.split(",") .map((tag: string, index: number) => ( {tag.trim()} ))}
handleCheckboxChange(5)} />
handleCheckboxChange(6)} />
handleCheckboxChange(7)} />
handleCheckboxChange(8)} />

Information:

{detail?.statusName || getStatusName(detail?.statusId || 0)}

Komentar

{approval?.message}

{" "} {approval?.approvalBy?.fullname} |{" "} {formatDateToIndonesian(approval?.approvalDate)}

{/* {detail?.isPublish == false ? (
) : ( "" )} */} {(detail?.isPublish == false && detail.isPublishOnPolda == true) || (detail?.isPublish == false && detail?.isInternationalMedia == true && Number(detail?.statusId) == 2) ? (
{userLevelName?.includes("MABES") && ( )}
) : ( "" )} {/* {detail?.isPublish == true ? ( ) : ( "" )} */} Leave Comment
{status == "2" ? files?.map((file, index) => (
{file.fileAlt handleImageLoad(e, index)} className={`h-[100px] object-cover ${ portraitMap[index] ? "w-auto" : "!w-[200px]" }`} />
{isUserMabesApprover && (
setupPlacement(index, "all", Boolean(e)) } />
setupPlacement( index, "mabes", Boolean(e) ) } />
setupPlacement( index, "polda", Boolean(e) ) } /> {wilayahPublish.polda && ( setSelectedPolda(data) } /> )}
setupPlacement( index, "international", Boolean(e) ) } />
)}
)) : ""}