"use client"; import React, { ChangeEvent, Fragment, 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 { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { register } from "module"; import { Switch } from "@/components/ui/switch"; import Cookies from "js-cookie"; import { createMedia, deleteFile, deleteMedia, getTagsBySubCategoryId, listEnableCategory, updateFilePlacements, uploadThumbnail, } from "@/service/content/content"; import { detailMedia } from "@/service/curated-content/curated-content"; import { Badge } from "@/components/ui/badge"; import { CloudUpload, MailIcon } from "lucide-react"; import dynamic from "next/dynamic"; import { useDropzone } from "react-dropzone"; import { Icon } from "@iconify/react/dist/iconify.js"; import Image from "next/image"; import { error, loading } from "@/lib/swal"; import { getCsrfToken } from "@/service/auth"; import { Upload } from "tus-js-client"; import { useTranslations } from "next-intl"; import { Link } from "@/i18n/routing"; import { htmlToString } from "@/utils/globals"; import { getUserLevelForAssignments } from "@/service/task"; import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { v4 as uuidv4 } from "uuid"; import { getCookiesDecrypt } from "@/lib/utils"; import { translateText } from "@/service/content/ai"; import { close } from "@/config/swal"; 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 PlacementType = "all" | "mabes" | "polda" | "international" | string; interface FilePlacement { mediaFileId: number; placements?: PlacementType[]; } interface TempFileItem { id: number | string; } type Detail = { id: string; title: string; description: string; htmldescription: string; slug: string; categoryId: number; category: { id: string; name: string; }; publishedFor: string; publishedForObject: { id: number; name: string; }; creatorName: string; categoryName: string; thumbnailLink: string; tags: string; }; type Option = { id: string; name: string; }; interface Destination { id: string; name: string; subDestination?: SubDestination[]; } interface SubDestination { id: string; name: string; } const CustomEditor = dynamic( () => { return import("@/components/editor/custom-editor"); }, { ssr: false } ); interface FileWithPreview extends File { id: string; preview: string; } export default function FormImageUpdate() { const MySwal = withReactContent(Swal); const router = useRouter(); const { id } = useParams() as { id: string }; const editor = useRef(null); const roleId = getCookiesDecrypt("urie"); type ImageSchema = z.infer; let progressInfo: any = []; let counterUpdateProgress = 0; const [progressList, setProgressList] = useState([]); let uploadPersen = 0; const isDetailOfRegionShowed = false; const [isStartUpload, setIsStartUpload] = useState(false); const [counterProgress, setCounterProgress] = useState(0); const t = useTranslations("Form"); const [selectedFiles, setSelectedFiles] = useState([]); const taskId = Cookies.get("taskId"); const scheduleId = Cookies.get("scheduleId"); const scheduleType = Cookies.get("scheduleType"); 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 [articleBody, setArticleBody] = useState(""); const [files, setFiles] = useState([]); const [filesTemp, setFilesTemp] = useState([]); const [publishedFor, setPublishedFor] = useState([]); const [thumbnailFile, setThumbnailFile] = useState(null); const inputRef = useRef(null); const [isLoadingTranslate, setIsLoadingTranslate] = useState(false); const [translatedContent, setTranslatedContent] = React.useState(""); const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id"); const handleThumbnailChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { setThumbnailFile(file); } }; const [fileUnitSelections, setFileUnitSelections] = useState< Array<{ semua: boolean; nasional: boolean; wilayah: boolean; international: boolean; polda: boolean; satker: boolean; }> >([]); // State global untuk kompatibilitas (akan dihapus nanti) const [unitSelection, setUnitSelection] = useState({ semua: false, nasional: false, wilayah: false, international: false, polda: false, satker: false, }); const [checkedLevels, setCheckedLevels] = useState>(new Set()); const [listDest, setListDest] = useState([]); const [isLoading, setIsLoading] = useState(false); const [expandedPolda, setExpandedPolda] = useState>( {} ); const [fileCheckedLevels, setFileCheckedLevels] = useState< Array> >([]); const [isUpdatingFromMainCheckbox, setIsUpdatingFromMainCheckbox] = useState(false); const [mainCheckboxChangeType, setMainCheckboxChangeType] = useState(""); useEffect(() => { async function fetchPoldaPolres() { setIsLoading(true); try { const response = await getUserLevelForAssignments(); setListDest(response?.data?.data.list); const initialExpandedState = response?.data?.data.list.reduce( (acc: any, polda: any) => { acc[polda.id] = false; return acc; }, {} ); setExpandedPolda(initialExpandedState); console.log("polres", initialExpandedState); } catch (error) { console.error("Error fetching Polda/Polres data:", error); } finally { setIsLoading(false); } } fetchPoldaPolres(); }, []); // useEffect untuk sinkronisasi checkbox modal dengan checkbox utama useEffect(() => { if ( listDest.length > 0 && isUpdatingFromMainCheckbox && mainCheckboxChangeType ) { syncModalWithMainCheckbox(); } }, [isUpdatingFromMainCheckbox, mainCheckboxChangeType]); // useEffect untuk update checkbox utama ketika pilihan modal berubah useEffect(() => { if (!isUpdatingFromMainCheckbox && listDest.length > 0) { updateMainCheckboxFromModalLegacy(); } }, [checkedLevels, isUpdatingFromMainCheckbox]); // Fungsi untuk update checkbox utama berdasarkan checkbox modal (global/legacy) const updateMainCheckboxFromModalLegacy = () => { if (!isUpdatingFromMainCheckbox && listDest.length > 0) { // Hitung item yang dipilih berdasarkan checkedLevels const checkedPoldaCount = listDest.filter( (item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI" && checkedLevels.has(Number(item.id)) ).length; const satkerItem: any = listDest.find( (item: any) => item.name === "SATKER POLRI" ); const checkedSatkerCount = satkerItem ? (checkedLevels.has(Number(satkerItem.id)) ? 1 : 0) + (satkerItem.subDestination?.filter((sub: any) => checkedLevels.has(Number(sub.id)) ).length || 0) : 0; // Checkbox aktif jika ADA item yang dipilih dalam kategori tersebut const hasSelectedPolda = checkedPoldaCount > 0; const hasSelectedSatker = checkedSatkerCount > 0; // Update unitSelection berdasarkan yang dipilih di modal setUnitSelection((prev) => { const newState = { ...prev }; // Update individual checkboxes newState.polda = hasSelectedPolda; newState.satker = hasSelectedSatker; // Update checkbox "semua" berdasarkan semua checkbox yang aktif newState.semua = newState.nasional && newState.wilayah && newState.international && hasSelectedPolda && hasSelectedSatker; return newState; }); } }; // Fungsi untuk sinkronisasi checkbox modal dengan checkbox utama const syncModalWithMainCheckbox = () => { if (isUpdatingFromMainCheckbox) { const newCheckedLevels = new Set(checkedLevels); // Handle checklist actions - menambahkan semua item ke modal if (mainCheckboxChangeType === "polda_checked") { // Checklist semua polda listDest.forEach((item: any) => { if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { newCheckedLevels.add(Number(item.id)); } }); } else if (mainCheckboxChangeType === "satker_checked") { // Checklist satker const satkerItem: any = listDest.find( (item: any) => item.name === "SATKER POLRI" ); if (satkerItem) { newCheckedLevels.add(Number(satkerItem.id)); // Checklist semua sub-item yang ada di bawah SATKER (bukan POLRES) if (satkerItem.subDestination) { satkerItem.subDestination.forEach((sub: any) => { newCheckedLevels.add(Number(sub.id)); }); } } } else if (mainCheckboxChangeType === "semua_checked") { // Checklist semua item listDest.forEach((item: any) => { newCheckedLevels.add(Number(item.id)); // Checklist semua sub-item di bawah setiap item if (item.subDestination) { item.subDestination.forEach((sub: any) => { newCheckedLevels.add(Number(sub.id)); }); } }); } else if (mainCheckboxChangeType === "polda_unchecked") { // Clear polda dari checkedLevels, tapi jangan hapus SATKER POLRI listDest.forEach((item: any) => { if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { newCheckedLevels.delete(Number(item.id)); } }); } else if (mainCheckboxChangeType === "satker_unchecked") { // Clear satker dan semua sub-item di bawahnya dari checkedLevels const satkerItem: any = listDest.find( (item: any) => item.name === "SATKER POLRI" ); if (satkerItem) { newCheckedLevels.delete(Number(satkerItem.id)); if (satkerItem.subDestination) { satkerItem.subDestination.forEach((sub: any) => { newCheckedLevels.delete(Number(sub.id)); }); } } } else if (mainCheckboxChangeType === "semua_unchecked") { // Clear semua newCheckedLevels.clear(); } setCheckedLevels(newCheckedLevels); // Reset flag setelah sinkronisasi selesai setIsUpdatingFromMainCheckbox(false); setMainCheckboxChangeType(""); } }; // Fungsi untuk mengupdate state individual file const handleFileUnitChange = ( fileIndex: number, key: keyof typeof unitSelection, value: boolean ) => { setFileUnitSelections((prev) => { const newSelections = [...prev]; const currentSelection = { ...newSelections[fileIndex] }; if (key === "semua") { // Jika klik Semua, set semua value ke true/false currentSelection.semua = value; currentSelection.nasional = value; currentSelection.wilayah = value; currentSelection.international = value; currentSelection.polda = value; currentSelection.satker = value; // Update fileCheckedLevels untuk sinkronisasi dengan modal setFileCheckedLevels((prevLevels) => { const newArray = [...prevLevels]; const currentFileLevels = new Set( newArray[fileIndex] || new Set() ); if (value) { // Checklist semua item di modal listDest.forEach((item: any) => { currentFileLevels.add(Number(item.id)); if (item.subDestination) { item.subDestination.forEach((sub: any) => { currentFileLevels.add(Number(sub.id)); }); } }); } else { // Unchecklist semua item di modal currentFileLevels.clear(); } newArray[fileIndex] = currentFileLevels; return newArray; }); } else { // Jika wilayah dicentang, auto centang POLDA, SATKER if (key === "wilayah") { currentSelection.wilayah = value; if (value) { // Ketika wilayah dicentang, auto centang POLDA, SATKER currentSelection.polda = true; currentSelection.satker = true; // Update fileCheckedLevels untuk mengisi semua POLDA dan SATKER POLRI ketika wilayah dicentang setFileCheckedLevels((prevLevels) => { const newArray = [...prevLevels]; const currentFileLevels = new Set( newArray[fileIndex] || new Set() ); // Checklist semua POLDA di modal listDest.forEach((item: any) => { if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { currentFileLevels.add(Number(item.id)); } }); // Checklist SATKER POLRI dan semua sub-itemsnya const satkerItem = listDest.find( (item: any) => item.name === "SATKER POLRI" ); if (satkerItem) { currentFileLevels.add(Number(satkerItem.id)); // Checklist semua sub-items di bawah SATKER POLRI if (satkerItem.subDestination) { satkerItem.subDestination.forEach((sub: any) => { currentFileLevels.add(Number(sub.id)); }); } } newArray[fileIndex] = currentFileLevels; return newArray; }); } else { // Ketika wilayah di-uncheck, uncheck POLDA, SATKER dan hapus data POLDA dari fileCheckedLevels currentSelection.polda = false; currentSelection.satker = false; // Update fileCheckedLevels untuk menghapus semua POLDA dan SATKER POLRI ketika wilayah di-uncheck setFileCheckedLevels((prevLevels) => { const newArray = [...prevLevels]; const currentFileLevels = new Set( newArray[fileIndex] || new Set() ); // Hapus semua POLDA dari modal listDest.forEach((item: any) => { if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { currentFileLevels.delete(Number(item.id)); } }); // Hapus SATKER POLRI dan semua sub-itemsnya const satkerItem = listDest.find( (item: any) => item.name === "SATKER POLRI" ); if (satkerItem) { currentFileLevels.delete(Number(satkerItem.id)); // Hapus semua sub-items di bawah SATKER POLRI if (satkerItem.subDestination) { satkerItem.subDestination.forEach((sub: any) => { currentFileLevels.delete(Number(sub.id)); }); } } newArray[fileIndex] = currentFileLevels; return newArray; }); } } else { // Update salah satu saja currentSelection[key] = value; } // Cek apakah semua selain "semua" sudah dicentang const allChecked = [ "nasional", "wilayah", "international", "polda", "satker", ].every((k) => currentSelection[k as keyof typeof unitSelection]); currentSelection.semua = allChecked; } newSelections[fileIndex] = currentSelection; return newSelections; }); }; // Fungsi untuk mengupdate checklist levels untuk file tertentu const handleFileCheckboxChangePlacement = ( fileIndex: number, levelId: number ) => { setFileCheckedLevels((prev) => { const newArray = [...prev]; const currentFileLevels = new Set(newArray[fileIndex]); const isCurrentlyChecked = currentFileLevels.has(levelId); if (isCurrentlyChecked) { currentFileLevels.delete(levelId); // Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya const poldaItem = listDest.find( (item: any) => Number(item.id) === levelId ) as any; if ( poldaItem && poldaItem.subDestination && poldaItem.name !== "SATKER POLRI" ) { poldaItem.subDestination.forEach((polres: any) => { currentFileLevels.delete(Number(polres.id)); }); } // Jika ini adalah SATKER POLRI yang di-unchecklist, unchecklist juga semua sub-item di bawahnya if (poldaItem && poldaItem.name === "SATKER POLRI") { poldaItem.subDestination?.forEach((subItem: any) => { currentFileLevels.delete(Number(subItem.id)); }); } } else { currentFileLevels.add(levelId); // Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya const satkerItem = listDest.find( (item: any) => Number(item.id) === levelId ) as any; if (satkerItem && satkerItem.name === "SATKER POLRI") { // Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES) satkerItem.subDestination?.forEach((subItem: any) => { currentFileLevels.add(Number(subItem.id)); }); } } newArray[fileIndex] = currentFileLevels; // Update checkbox utama berdasarkan perubahan di modal // Pindahkan ke sini agar state sudah ter-update setTimeout(() => updateMainCheckboxFromModal(fileIndex), 0); return newArray; }); }; // Fungsi untuk mengupdate checkbox utama berdasarkan checklist di modal const updateMainCheckboxFromModal = (fileIndex: number) => { setFileUnitSelections((prev) => { const newSelections = [...prev]; const currentSelection = { ...newSelections[fileIndex] }; const currentFileLevels = fileCheckedLevels[fileIndex]; if (!currentFileLevels) return prev; // Hitung total POLDA yang ada (bukan SATKER POLRI) const totalPoldaCount = listDest.filter( (item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI" ).length; // Hitung berapa banyak POLDA yang ter-checklist (bukan SATKER POLRI) const checkedPoldaCount = listDest.reduce((total: number, item: any) => { if ( item.levelNumber === 2 && item.name !== "SATKER POLRI" && currentFileLevels.has(Number(item.id)) ) { return total + 1; } return total; }, 0); // Cek apakah SATKER POLRI ter-checklist const satkerItem = listDest.find( (item: any) => item.name === "SATKER POLRI" ); const isSatkerChecked = satkerItem && currentFileLevels.has(Number(satkerItem.id)); // Update checkbox berdasarkan kondisi // POLDA aktif jika ada minimal 1 POLDA ter-checklist currentSelection.polda = checkedPoldaCount > 0; currentSelection.satker = Boolean(isSatkerChecked); // Update checkbox "semua" berdasarkan semua checkbox yang aktif currentSelection.semua = currentSelection.nasional && currentSelection.wilayah && currentSelection.international && currentSelection.polda && currentSelection.satker; newSelections[fileIndex] = currentSelection; return newSelections; }); }; const toggleExpand = (id: number) => { setExpandedPolda((prev) => ({ ...prev, [id]: !prev[id], })); }; // Fungsi untuk menangani "Pilih Semua" sub-items di bawah SATKER POLRI const handleSelectAllSubItems = (fileIndex: number, polda: any) => { setFileCheckedLevels((prev) => { const newArray = [...prev]; const currentFileLevels = new Set(newArray[fileIndex]); // Cek apakah semua sub-items sudah ter-checklist const allSubItemsChecked = polda.subDestination?.every((sub: any) => currentFileLevels.has(Number(sub.id)) ); if (allSubItemsChecked) { // Jika semua sudah ter-checklist, unchecklist semuanya polda.subDestination?.forEach((sub: any) => { currentFileLevels.delete(Number(sub.id)); }); } else { // Jika belum semua ter-checklist, checklist semuanya // Checklist SATKER POLRI juga jika belum ter-checklist if (!currentFileLevels.has(Number(polda.id))) { currentFileLevels.add(Number(polda.id)); } // Checklist semua sub-items polda.subDestination?.forEach((sub: any) => { currentFileLevels.add(Number(sub.id)); }); } newArray[fileIndex] = currentFileLevels; // Update checkbox utama berdasarkan perubahan di modal setTimeout(() => updateMainCheckboxFromModal(fileIndex), 0); return newArray; }); }; const options: Option[] = [ { id: "all", name: "SEMUA" }, { id: "5", name: "UMUM" }, { id: "6", name: "JOURNALIS" }, { id: "7", name: "POLRI" }, { id: "8", name: "KSP" }, ]; const [selectedTarget, setSelectedTarget] = useState( detail?.category.id ); // const [unitSelection, setUnitSelection] = useState({ // allUnit: false, // mabes: false, // polda: false, // polres: false, // }); let fileTypeId = "1"; // const { getRootProps, getInputProps } = useDropzone({ // onDrop: (acceptedFiles) => { // // setFiles(acceptedFiles.map((file) => Object.assign(file))); // setFiles((prevFiles) => [ // ...prevFiles, // ...acceptedFiles.map((file) => // Object.assign(file, { // preview: URL.createObjectURL(file), // }) // ), // ]); // }, // accept: { // "image/*": [], // }, // }); const { getRootProps, getInputProps } = useDropzone({ onDrop: (acceptedFiles) => { setFiles((prevFiles) => [ ...prevFiles, ...acceptedFiles.map((file) => Object.assign(file, { id: uuidv4(), // generate unique id preview: URL.createObjectURL(file), }) ), ]); }, accept: { "image/*": [], }, }); const { control, handleSubmit, setValue, getValues, formState: { errors }, } = useForm({ resolver: zodResolver(imageSchema), }); useEffect(() => { async function initState() { getCategories(); } initState(); }, []); const handleAddTag = (e: React.KeyboardEvent) => { if (e.key === "Enter" && e.currentTarget.value.trim()) { e.preventDefault(); const newTag = e.currentTarget.value.trim(); if (!tags.includes(newTag)) { setTags((prevTags) => [...prevTags, newTag]); if (inputRef.current) { inputRef.current.value = ""; } } } }; const handleRemoveTag = (index: number) => { setTags((prevTags) => prevTags.filter((_, i) => i !== index)); }; const handleEditTag = (index: number, newValue: string) => { setTags((prevTags) => prevTags.map((tag, i) => (i === index ? newValue : tag)) ); }; const getCategories = async () => { try { const category = await listEnableCategory(fileTypeId); const resCategory: Category[] = category?.data?.data?.content; 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); const response = await getTagsBySubCategoryId(findCategory.id); setTags(response?.data?.data); } } } catch (error) { console.error("Failed to fetch categories:", error); } }; useEffect(() => { async function initState() { if (id) { const response = await detailMedia(id); const details = response?.data?.data; setDetail(details); // Set the selected target to the category ID from details setSelectedTarget(String(details.category.id)); setTempFile(details?.files); setValue("title", details.title); setValue("description", details.htmlDescription); setValue("creatorName", details.creatorName); setTimeout(() => { setValue("title", details.title); setValue("description", details.htmlDescription); setValue("creatorName", details.creatorName); }, 500); if (details?.files) { const formattedFiles = details.files.map((file: any) => ({ ...file, id: file.id, fileName: file.fileName, size: file.size, thumbnailFileUrl: file.thumbnailFileUrl, url: file.url, })); setFiles(formattedFiles); // Inisialisasi filePlacements dari detail const initialFilePlacements = details.files.map((file: any) => { if (file.placements) { // Map dari format backend ke format internal const mappedPlacements = file.placements .split(",") .map((p: string) => { const trimmed = p.trim(); switch (trimmed) { case "all": return "all"; case "mabes": return "nasional"; case "polda": return "wilayah"; case "satker": return "satker"; case "international": return "international"; default: return trimmed; } }); return mappedPlacements; } return []; }); setFilePlacements(initialFilePlacements); // Inisialisasi fileCheckedLevels dari detail const initialFileCheckedLevels = details.files.map((file: any) => { if (file.customLocationPlacements) { const levelIds = file.customLocationPlacements .split(",") .map((id: string) => Number(id.trim())) .filter((id: number) => !isNaN(id)); return new Set(levelIds); } return new Set(); }); setFileCheckedLevels(initialFileCheckedLevels); // Inisialisasi fileUnitSelections dari detail const initialFileUnitSelections = details.files.map((file: any) => { const selection = { semua: false, nasional: false, wilayah: false, international: false, polda: false, satker: false, }; if (file.placements) { const placements = file.placements .split(",") .map((p: string) => p.trim()); // Map dari format backend ke checkbox if (placements.includes("all")) { selection.semua = true; selection.nasional = true; selection.wilayah = true; selection.international = true; selection.polda = true; selection.satker = true; } else { if (placements.includes("mabes")) { selection.nasional = true; } if (placements.includes("wilayah")) { selection.wilayah = true; } if (placements.includes("polda")) { selection.polda = true; selection.wilayah = true; // Auto-check wilayah when polda is present } if (placements.includes("satker")) { selection.satker = true; selection.wilayah = true; // Auto-check wilayah when satker is present } if (placements.includes("international")) { selection.international = true; } } } return selection; }); setFileUnitSelections(initialFileUnitSelections); } if (details?.publishedFor) { // Split string "7" to an array ["7"] if needed setPublishedFor(details.publishedFor.split(",")); } if (details?.tags) { setTags(details.tags.split(",").map((tag: string) => tag.trim())); } } } initState(); }, [id, setValue]); const handleCheckboxChange = (id: string) => { if (id === "all") { const allOptions = options .filter((opt) => opt.id !== "all") .map((opt) => opt.id); setPublishedFor( publishedFor.length === allOptions.length ? [] : allOptions ); } else { setPublishedFor((prev) => prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id] ); } }; const [filePlacements, setFilePlacements] = useState([]); const getPlacement = () => { const temp = []; for (let i = 0; i < filePlacements?.length; i++) { const file = files[i] as any; if ( file.id && filePlacements[file.id] && filePlacements[file.id].length > 0 ) { const now = filePlacements[file.id]; const normalizedNow = now.map((item): PlacementType => { const value = String(item); if (value === "nasional") return "mabes"; if (value === "wilayah") return "polda"; if (value === "semua") return "all"; return item as PlacementType; }); const uniqueNow = Array.from(new Set(normalizedNow)); const nowArr = uniqueNow.join(","); // Dapatkan checked levels untuk file ini const currentFileCheckedLevels = fileCheckedLevels[file.id] ? Array.from(fileCheckedLevels[file.id]) : []; const data = { mediaFileId: file.id, placements: nowArr, customLocationPlacements: currentFileCheckedLevels.join(","), }; temp.push(data); } } return temp; }; const save = async (data: ImageSchema) => { loading(); const finalTags = tags.join(", "); // ✅ tentukan isi description sesuai pilihan bahasa const descFinal = selectedLang === "en" && translatedContent ? translatedContent : data.description; const requestData = { ...data, id: detail?.id, title: data.title, description: htmlToString(descFinal), // versi plain text htmlDescription: descFinal, // versi HTML fileTypeId, categoryId: selectedTarget, subCategoryId: selectedTarget, uploadedBy: "2b7c8d83-d298-4b19-9f74-b07924506b58", statusId: "1", publishedFor: publishedFor.join(","), creatorName: data.creatorName, tags: finalTags, isYoutube: false, isInternationalMedia: false, }; console.log("Form Data Submitted:", requestData); console.log("getPlacement(): ", getPlacement()); const response = await createMedia(requestData); if (response?.error) { error(response?.message); return false; } const formMedia = new FormData(); const thumbnail = thumbnailFile || files[0]; formMedia.append("file", thumbnail); const responseThumbnail = await uploadThumbnail(id, formMedia); if (responseThumbnail?.error) { error(responseThumbnail?.message); return false; } const progressInfoArr = []; for (const item of files) { progressInfoArr.push({ percentage: 0, fileName: item.name }); } progressInfo = progressInfoArr; setIsStartUpload(true); setProgressList(progressInfoArr); // Update file placements const responseFilePlacements = await updateFilePlacements(getPlacement()); if (responseFilePlacements?.error) { error(responseFilePlacements?.message); return false; } close(); // showProgress(); console.log("files:", files); files.map(async (item: any, index: number) => { await uploadResumableFile( index, String(id), item, fileTypeId == "2" || fileTypeId == "4" ? item.duration : "0" ); }); MySwal.fire({ title: "Sukses", text: "Data berhasil disimpan.", icon: "success", confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { router.push("/in/contributor/content/image"); }); }; async function uploadResumableFile( idx: number, id: string, file: any, duration: string ) { // console.log(idx, id, file, duration); // const placements = getPlacement(file.placements); // console.log("Placementttt: : ", placements); const resCsrf = await getCsrfToken(); const csrfToken = resCsrf?.data?.token; // console.log("CSRF TOKEN : ", csrfToken); const headers = { "X-XSRF-TOKEN": csrfToken, }; if (!file.secondaryUrl || file.secondaryUrl == "") { const upload = new Upload(file, { endpoint: `${process.env.NEXT_PUBLIC_API}/media/file/upload`, headers: headers, retryDelays: [0, 3000, 6000, 12_000, 24_000], chunkSize: 20_000, metadata: { mediaid: id, filename: file.name, filetype: file.type, duration, isWatermark: "true", }, onBeforeRequest: function (req) { var xhr = req.getUnderlyingObject(); xhr.withCredentials = true; }, onError: async (e: any) => { // console.log("Error upload :", e); error(e); }, onChunkComplete: ( chunkSize: any, bytesAccepted: any, bytesTotal: any ) => { const uploadPersen = Math.floor((bytesAccepted / bytesTotal) * 100); progressInfo[idx].percentage = uploadPersen; counterUpdateProgress++; // console.log(counterUpdateProgress); setProgressList(progressInfo); setCounterProgress(counterUpdateProgress); }, onSuccess: async () => { uploadPersen = 100; progressInfo[idx].percentage = 100; counterUpdateProgress++; setCounterProgress(counterUpdateProgress); successTodo(); }, }); upload.start(); } } const onSubmit = (data: ImageSchema) => { MySwal.fire({ title: "Simpan Data", text: "Apakah Anda yakin ingin menyimpan data ini?", icon: "warning", showCancelButton: true, cancelButtonColor: "#d33", confirmButtonColor: "#3085d6", confirmButtonText: "Simpan", }).then((result) => { if (result.isConfirmed) { save(data); } }); }; const successSubmit = (redirect: string) => { MySwal.fire({ title: "Sukses", text: "Data berhasil disimpan.", icon: "success", confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { router.push(redirect); }); }; function successTodo() { let counter = 0; for (const element of progressInfo) { if (element.percentage == 100) { counter++; } } if (counter == progressInfo.length) { setIsStartUpload(false); // hideProgress(); Cookies.remove("idCreate"); successSubmit("/in/contributor/content/image/"); } } const handleRemoveAllFiles = () => { setFiles([]); }; const renderFilePreview = (file: FileWithPreview | any) => { if (file?.preview || file instanceof File) { return ( {file.name} ); } else if (file.thumbnailFileUrl) { return ( {file.fileName} ); } else { return ; } }; const handleRemoveFile = (file: FileWithPreview) => { const uploadedFiles = files; const filtered = uploadedFiles.filter((i) => i.name !== file.name); setFiles([...filtered]); }; const fileList = files.map((file: any) => (
{renderFilePreview(file)}
{file.fileName || file.name}
{Math.round(file.size / 100) / 10 > 1000 ? ( <>{(Math.round(file.size / 100) / 10000).toFixed(1)} ) : ( <>{(Math.round(file.size / 100) / 10).toFixed(1)} )} {" kb"}
)); type PlacementType = "all" | "mabes" | "polda" | "international" | string; interface FilePlacement { mediaFileId: number; placements?: PlacementType[]; } interface TempFileItem { id: number | string; // tambahkan properti lain kalau ada } const [tempFile, setTempFile] = useState([]); const setupPlacement = ( index: number, placement: string, checked: boolean ) => { let temp = [...filePlacements]; if (checked) { if (placement === "all") { temp[index] = ["all", "mabes", "polda", "international"]; setFileCheckedLevels((prevLevels) => { const newArray = [...prevLevels]; const currentFileLevels = new Set( newArray[index] || new Set() ); listDest.forEach((item: any) => { currentFileLevels.add(Number(item.id)); if (item.subDestination) { item.subDestination.forEach((sub: any) => { currentFileLevels.add(Number(sub.id)); }); } }); newArray[index] = currentFileLevels; return newArray; }); setFileUnitSelections((prevSelections) => { const newSelections = [...prevSelections]; const currentSelection = { ...newSelections[index] }; currentSelection.nasional = true; currentSelection.wilayah = true; currentSelection.international = true; currentSelection.polda = true; // currentSelection.polres = true; currentSelection.satker = true; currentSelection.semua = true; newSelections[index] = currentSelection; return newSelections; }); } else if (placement === "satker") { const now = temp[index] || []; if (!now.includes("satker")) { now.push("satker"); } temp[index] = now; } else { const now = temp[index] || []; if (!now.includes(placement)) { now.push(placement); } const nonSatkerItems = now.filter( (item) => item !== "satker" && item !== "all" ); if (nonSatkerItems.length === 3 && !now.includes("all")) { now.push("all"); } temp[index] = now; } } else { if (placement === "all") { temp[index] = []; setFileCheckedLevels((prevLevels) => { const newArray = [...prevLevels]; const currentFileLevels = new Set( newArray[index] || new Set() ); currentFileLevels.clear(); newArray[index] = currentFileLevels; return newArray; }); // Update fileUnitSelections untuk checkbox tingkat utama setFileUnitSelections((prevSelections) => { const newSelections = [...prevSelections]; const currentSelection = { ...newSelections[index] }; // Set semua checkbox tingkat utama ke false currentSelection.nasional = false; currentSelection.wilayah = false; currentSelection.international = false; currentSelection.polda = false; // currentSelection.polres = false; currentSelection.satker = false; currentSelection.semua = false; newSelections[index] = currentSelection; return newSelections; }); } else { const now = temp[index]?.filter((a) => a !== placement); console.log("now", now); temp[index] = now; if (placement === "wilayah") { // Ketika wilayah di-uncheck, hapus wilayah, polda, dan satker const now = temp[index]?.filter( (a) => a !== "wilayah" && a !== "polda" && a !== "satker" ); temp[index] = now; } else if (placement === "polda") { // Ketika polda di-uncheck, hapus polda dari filePlacements const now = temp[index]?.filter((a) => a !== "polda"); temp[index] = now; } else if (placement === "satker") { // Ketika satker di-uncheck, hapus satker dari filePlacements const now = temp[index]?.filter((a) => a !== "satker"); temp[index] = now; } else { const now = temp[index]?.filter((a) => a !== placement); temp[index] = now; } // Hapus "all" jika tidak semua item ter-checklist if (now.includes("all")) { const nonSatkerItems = now.filter( (item) => item !== "satker" && item !== "all" ); if (nonSatkerItems.length < 3) { const newData = now.filter((b) => b !== "all"); temp[index] = newData; } } } } setFilePlacements(temp); // Update checklist levels di modal berdasarkan placement yang diubah updateModalChecklistLevels(index, placement, checked); }; // Fungsi untuk mengupdate checklist levels di modal berdasarkan placement const updateModalChecklistLevels = ( fileIndex: number, placement: string, checked: boolean ) => { if (!listDest || listDest.length === 0) return; setFileCheckedLevels((prev) => { const newArray = [...prev]; const currentFileLevels = new Set(newArray[fileIndex]); if (checked) { if (placement === "polda") { // Checklist semua POLDA (bukan SATKER POLRI) listDest.forEach((item: any) => { if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { currentFileLevels.add(Number(item.id)); } }); } else if (placement === "satker") { // Checklist SATKER POLRI dan semua sub-item di bawahnya const satkerItem: any = listDest.find( (item: any) => item.name === "SATKER POLRI" ); if (satkerItem) { currentFileLevels.add(Number(satkerItem.id)); if (satkerItem.subDestination) { satkerItem.subDestination.forEach((sub: any) => { currentFileLevels.add(Number(sub.id)); }); } } } } else { if (placement === "polda") { // Unchecklist semua POLDA listDest.forEach((item: any) => { if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { currentFileLevels.delete(Number(item.id)); } }); } else if (placement === "satker") { // Unchecklist SATKER POLRI dan semua sub-item di bawahnya const satkerItem: any = listDest.find( (item: any) => item.name === "SATKER POLRI" ); if (satkerItem) { currentFileLevels.delete(Number(satkerItem.id)); if (satkerItem.subDestination) { satkerItem.subDestination.forEach((sub: any) => { currentFileLevels.delete(Number(sub.id)); }); } } } } newArray[fileIndex] = currentFileLevels; return newArray; }); }; // const setupPlacement = (id: number | string, placement: PlacementType) => { // console.log(`FileDestination.leng:: ${id}_${placement}`); // const arrayFile: FilePlacement[] = []; // for (let i = 0; i < tempFile?.length; i++) { // const element = tempFile[i]; // if (element.id == id) { // const findPlacementIdx = filePlacements.findIndex( // (o) => Number(o.mediaFileId) === Number(id) // ); // if (findPlacementIdx > -1) { // const findPlacement = filePlacements[findPlacementIdx]; // if (findPlacement?.placements?.includes(placement)) { // if (placement === "all") { // findPlacement.placements = undefined; // } else { // findPlacement.placements = findPlacement.placements.filter( // (val) => val !== placement // ); // if (findPlacement.placements?.includes("all")) { // findPlacement.placements = findPlacement.placements.filter( // (val) => val !== "all" // ); // } // } // } else if (placement === "all") { // findPlacement.placements = [ // "all", // "mabes", // "polda", // "international", // ]; // } else if (findPlacement.placements) { // findPlacement.placements = [...findPlacement.placements, placement]; // } else { // findPlacement.placements = [placement]; // } // } else { // const file: FilePlacement = { // mediaFileId: Number(element.id), // placements: [placement], // }; // arrayFile.push(file); // } // } // } // const finalPlacements = [...filePlacements, ...arrayFile]; // setFilePlacements(finalPlacements); // console.log("FileDestination.leng::", finalPlacements); // }; function success() { MySwal.fire({ title: "Sukses", icon: "success", confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then((result) => { if (result.isConfirmed) { // window.location.reload(); } }); } const handleDeleteFile = (id: number) => { MySwal.fire({ title: "Hapus file", text: "Apakah Anda yakin ingin menghapus file ini?", icon: "warning", showCancelButton: true, cancelButtonColor: "#3085d6", confirmButtonColor: "#d33", confirmButtonText: "Hapus", }).then((result) => { if (result.isConfirmed) { doDelete(id); } }); }; async function doDelete(id: number) { const data = { id }; try { const response = await deleteFile(data); if (response?.error) { error(response.message); return; } setFiles((prevFiles: any) => prevFiles.filter((file: any) => file.id !== id) ); success(); } catch (err) { error("Terjadi kesalahan saat menghapus file"); } } return (
{detail !== undefined ? (

{t("form-image", { defaultValue: "Form Image" })}

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

{errors.title.message}

)}
{roleId === "14" && ( )}
{/* Pilihan bahasa untuk posting */} {roleId === "14" && (
)} {/* Editor Bahasa Indonesia */} ( )} /> {/* Editor Bahasa Inggris */} {translatedContent && (
setTranslatedContent(val)} initialData={translatedContent} />
)} {errors.description?.message && (

{errors.description.message}

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

{errors.description.message}

)}
*/}
{/* */}

{/* Drop files here or click to upload. */} {t("drag-file", { defaultValue: "Drag File" })}

{t("upload-file-max", { defaultValue: "Upload File Max", })}
{files.length ? (
{fileList}
{/* */}
) : null} {files.length > 0 && (
{files.map((file: any, index: any) => (
{file.fileName}
{/*
Pengaturan Distribusi
*/} {/* Checkbox Tingkat Utama */}
{[ { key: "semua", label: "Semua" }, { key: "nasional", label: "Nasional", }, { key: "wilayah", label: "Wilayah" }, { key: "international", label: "Internasional", }, ].map((item, idx) => (
{ handleFileUnitChange( index, item.key as keyof typeof unitSelection, value as boolean ); setupPlacement( index, item.key, Boolean(value) ); }} />
))}
{/* Detail Wilayah */} {fileUnitSelections[index]?.wilayah && isDetailOfRegionShowed && (

Detail Wilayah:

{/* Checkbox Sub-kategori dengan tombol Kustom sejajar */}
{[ { key: "polda", label: "POLDA" }, { key: "satker", label: "SATKER", }, ].map((item, idx) => (
{ handleFileUnitChange( index, item.key as keyof typeof unitSelection, value as boolean ); setupPlacement( index, item.key, Boolean(value) ); }} />
))} {/* Tombol Kustom sejajar dengan checkbox */}
Daftar Wilayah POLDA dan SATKER
{listDest.map( (polda: any) => (
{/* Header POLDA */}
{/* Tombol expand hanya untuk SATKER POLRI */} {polda.name === "SATKER POLRI" && polda.subDestination && ( )}
{/* Sub-items hanya untuk SATKER POLRI */} {polda.name === "SATKER POLRI" && polda.subDestination && expandedPolda[ polda.id ] && (
{/* Tombol Pilih Semua untuk sub-items */}
{(() => { const allSubItemsChecked = polda.subDestination?.every( ( sub: any ) => fileCheckedLevels[ index ]?.has( Number( sub.id ) ) ); return ( ); })()}
{polda.subDestination.map( ( sub: any ) => ( ) )}
)}
) )}
)}
))}
)}
( )} /> {errors.creatorName?.message && (

{errors.creatorName.message}

)}
{/*
Thumbnail Gambar Utama
*/}
{ const file = e.target.files?.[0]; if (file) { setThumbnailFile(file); } }} className="dark:border dark:border-gray-500 dark:rounded-lg" /> Thumbnail Preview
{tags.map((tag, index) => ( {/* Hidden span untuk ukur lebar teks */} {tag || " "} handleEditTag(index, e.target.value)} style={{ width: `${Math.max(tag.length, 1)}ch`, }} className="bg-black text-white border-none focus:outline-none" /> ))}
{/*
{detail?.tags?.split(",").map((tag, index) => ( {tag.trim()} ))}
*/}
{options.map((option: Option) => (
opt.id !== "all").length : publishedFor.includes(option.id) } onCheckedChange={() => handleCheckboxChange(option.id)} />
))}

{t("suggestion-box", { defaultValue: "Suggestion Box" })} (0)

{t("information", { defaultValue: "Information" })}:

{/*

{detail?.status}

*/}
) : ( "" )}
); }