From 82e8dfafc928d5286daf4ca1a7adf4207074f995 Mon Sep 17 00:00:00 2001 From: hanif salafi Date: Thu, 11 Sep 2025 08:15:02 +0700 Subject: [PATCH] feat: update edit media --- components/form/content/audio-update-form.tsx | 958 ++++++++++++-- components/form/content/image-update-form.tsx | 683 ++++------ components/form/content/teks-update-form.tsx | 1145 +++++++++++++++-- components/form/content/video-update-form.tsx | 784 +++++++++-- 4 files changed, 2872 insertions(+), 698 deletions(-) diff --git a/components/form/content/audio-update-form.tsx b/components/form/content/audio-update-form.tsx index 79b7836a..e15cd23c 100644 --- a/components/form/content/audio-update-form.tsx +++ b/components/form/content/audio-update-form.tsx @@ -34,6 +34,7 @@ import { deleteFile, getTagsBySubCategoryId, listEnableCategory, + updateFilePlacements, uploadThumbnail, } from "@/service/content/content"; import { detailMedia } from "@/service/curated-content/curated-content"; @@ -51,6 +52,16 @@ import { Upload } from "tus-js-client"; import { useTranslations } from "next-intl"; import dynamic from "next/dynamic"; 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"; const audioSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -66,6 +77,17 @@ type Category = { 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; @@ -83,9 +105,21 @@ type Detail = { }; interface FileWithPreview extends File { + id: string; preview: string; } +interface Destination { + id: string; + name: string; + subDestination?: SubDestination[]; +} + +interface SubDestination { + id: string; + name: string; +} + type Option = { id: string; name: string; @@ -131,9 +165,38 @@ export default function FormAudioUpdate() { const [selectedTarget, setSelectedTarget] = useState(""); const [publishedFor, setPublishedFor] = useState([]); const inputRef = useRef(null); - const [selectedOptions, setSelectedOptions] = useState<{ - [fileId: number]: string[]; - }>({}); + 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(""); const options: Option[] = [ { id: "all", name: "SEMUA" }, @@ -143,20 +206,25 @@ export default function FormAudioUpdate() { { id: "8", name: "KSP" }, ]; - const [unitSelection, setUnitSelection] = useState({ - allUnit: false, - mabes: false, - polda: false, - polres: false, - }); const [files, setFiles] = useState([]); const [prevFiles, setPrefFiles] = useState([]); + const [filePlacements, setFilePlacements] = useState([]); + const [tempFile, setTempFile] = useState([]); let fileTypeId = "4"; + const isDetailOfRegionShowed = false; const { getRootProps, getInputProps } = useDropzone({ onDrop: (acceptedFiles) => { - setFiles(acceptedFiles.map((file) => Object.assign(file))); + setFiles((prevFiles) => [ + ...prevFiles, + ...acceptedFiles.map((file) => + Object.assign(file, { + id: uuidv4(), // generate unique id + preview: URL.createObjectURL(file), + }) + ), + ]); }, accept: { "audio/*": [], @@ -183,6 +251,48 @@ export default function FormAudioUpdate() { setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index)); }; + 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]); + useEffect(() => { async function initState() { getCategories(); @@ -216,6 +326,123 @@ export default function FormAudioUpdate() { } }; + // 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(""); + } + }; + const handleAddTag = (e: React.KeyboardEvent) => { if (e.key === "Enter" && e.currentTarget.value.trim()) { e.preventDefault(); @@ -239,6 +466,546 @@ export default function FormAudioUpdate() { ); }; + // 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 getPlacement = () => { + const temp = []; + for (let i = 0; i < filePlacements?.length; i++) { + if (filePlacements[i]?.length !== 0) { + const now = filePlacements[i]; + let nowArr = now?.join(",")?.replaceAll("nasional", "mabes"); + nowArr = nowArr?.replaceAll("wilayah", "polda"); + nowArr = nowArr?.replaceAll("semua", "all"); + + // Dapatkan checked levels untuk file ini + const currentFileCheckedLevels = fileCheckedLevels[i] + ? Array.from(fileCheckedLevels[i]) + : []; + + const data = { + mediaFileId: files[i]?.id, + placements: nowArr, + customLocationPlacements: currentFileCheckedLevels.join(","), + }; + temp.push(data); + } + } + return temp; + }; + + const setupPlacement = ( + index: number, + placement: string, + checked: boolean + ) => { + let temp = [...filePlacements]; + if (checked) { + if (placement === "all") { + temp[index] = ["all", "mabes", "polda", "satker", "international"]; + + // Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik + setFileCheckedLevels((prevLevels) => { + const newArray = [...prevLevels]; + const currentFileLevels = new Set( + newArray[index] || new Set() + ); + + // 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)); + }); + } + }); + + 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 true + currentSelection.nasional = true; + currentSelection.wilayah = true; + currentSelection.international = true; + currentSelection.polda = true; + currentSelection.satker = true; + currentSelection.semua = true; + + newSelections[index] = currentSelection; + return newSelections; + }); + } else if (placement === "satker") { + // Ketika satker di-checklist, HANYA tambahkan satker saja + const now = temp[index] || []; + if (!now.includes("satker")) { + now.push("satker"); + } + temp[index] = now; + } else if (placement === "polda") { + // Ketika polda di-checklist, tambahkan polda ke filePlacements + const now = temp[index] || []; + if (!now.includes("polda")) { + now.push("polda"); + } + temp[index] = now; + } else if (placement === "wilayah") { + // Ketika wilayah dicentang, tambahkan wilayah, polda, dan satker + const now = temp[index] || []; + if (!now.includes("wilayah")) { + now.push("wilayah"); + } + if (!now.includes("polda")) { + now.push("polda"); + } + if (!now.includes("satker")) { + now.push("satker"); + } + temp[index] = now; + } else { + const now = temp[index] || []; + if (!now.includes(placement)) { + now.push(placement); + } + // Auto-checklist "all" jika nasional, wilayah, dan international ter-checklist + const requiredItems = ["nasional", "wilayah", "international"]; + const hasAllRequired = requiredItems.every(item => now.includes(item)); + if (hasAllRequired && !now.includes("all")) { + now.push("all"); + } + temp[index] = now; + } + } else { + if (placement === "all") { + temp[index] = []; + + // Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" di-unchecklist + setFileCheckedLevels((prevLevels) => { + const newArray = [...prevLevels]; + const currentFileLevels = new Set( + newArray[index] || new Set() + ); + + // Unchecklist semua item di modal + 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.satker = false; + currentSelection.semua = false; + + newSelections[index] = currentSelection; + return newSelections; + }); + } else { + 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 + const currentNow = temp[index] || []; + if (currentNow.includes("all")) { + const requiredItems = ["nasional", "wilayah", "international"]; + const hasAllRequired = requiredItems.every(item => currentNow.includes(item)); + if (!hasAllRequired) { + const newData = currentNow.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; + }); + }; + useEffect(() => { async function initState() { if (id) { @@ -261,15 +1028,99 @@ export default function FormAudioUpdate() { }, 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); setPrefFiles(details.files); - // setFiles(details.files); - const initialOptions: { [key: number]: string[] } = {}; - details.files.forEach((file: any) => { + setTempFile(details?.files); + + // Inisialisasi filePlacements dari detail + const initialFilePlacements = details.files.map((file: any) => { if (file.placements) { - initialOptions[file.id] = mapPlacementsToOptions(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 []; }); - setSelectedOptions(initialOptions); + 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; + } + if (placements.includes("satker")) { + selection.satker = true; + } + if (placements.includes("international")) { + selection.international = true; + } + } + } + + return selection; + }); + setFileUnitSelections(initialFileUnitSelections); } if (details?.publishedFor) { @@ -301,30 +1152,6 @@ export default function FormAudioUpdate() { initState(); }, [refresh, setValue]); - const mapPlacementsToOptions = (placements: string): string[] => { - const mapping: Record = { - all: "all", - mabes: "nasional", - polda: "wilayah", - polres: "internasional", - }; - - // Jika placements hanya "all", langsung aktifkan semua checkbox - if (placements.trim() === "all") { - return ["all", "nasional", "wilayah", "internasional"]; - } - - const options = placements - .split(",") - .map((p) => mapping[p.trim()]) - .filter(Boolean); - - const allSelected = ["nasional", "wilayah", "internasional"].every((opt) => - options.includes(opt) - ); - - return allSelected ? ["all", ...options] : options; - }; const handleCheckboxChange = (id: string) => { if (id === "all") { @@ -387,6 +1214,13 @@ export default function FormAudioUpdate() { setIsStartUpload(true); setProgressList(progressInfoArr); + // Update file placements + const responseFilePlacements = await updateFilePlacements(getPlacement()); + if (responseFilePlacements?.error) { + error(responseFilePlacements?.message); + return false; + } + close(); // showProgress(); files.map(async (item: any, index: number) => { @@ -582,37 +1416,6 @@ export default function FormAudioUpdate() { )); - const handleCheckboxChangeImage = (fileId: number, value: string) => { - setSelectedOptions((prev: any) => { - const currentSelections = prev[fileId] || []; - if (value === "all") { - // If "all" is clicked, toggle all options - if (currentSelections.includes("all")) { - return { ...prev, [fileId]: [] }; // Deselect all - } - return { - ...prev, - [fileId]: ["all", "nasional", "wilayah", "internasional"], - }; // Select all - } else { - // If any other checkbox is clicked, toggle that checkbox - const updatedSelections = currentSelections.includes(value) - ? currentSelections.filter((option: any) => option !== value) - : [...currentSelections, value]; - - // If all individual options are selected, include "all" automatically - const isAllSelected = ["nasional", "wilayah", "internasional"].every( - (opt) => updatedSelections.includes(opt) - ); - return { - ...prev, - [fileId]: isAllSelected - ? ["all", ...updatedSelections] - : updatedSelections.filter((opt: any) => opt !== "all"), - }; - } - }); - }; function success() { MySwal.fire({ @@ -797,8 +1600,14 @@ export default function FormAudioUpdate() { ) : null} - {prevFiles?.length > 0 && - prevFiles.map((file: any) => ( + {files.length > 0 && ( +
+ +
+ {files.map((file: any, index: any) => (
- ))} + ))} +
+
+ )} {/* {files.length > 0 && (
))} diff --git a/components/form/content/video-update-form.tsx b/components/form/content/video-update-form.tsx index e5dbe9e9..be3eb70a 100644 --- a/components/form/content/video-update-form.tsx +++ b/components/form/content/video-update-form.tsx @@ -25,6 +25,7 @@ import { } from "@/components/ui/select"; import { Checkbox } from "@/components/ui/checkbox"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { register } from "module"; import { Switch } from "@/components/ui/switch"; @@ -35,7 +36,9 @@ import { getTagsBySubCategoryId, listEnableCategory, uploadThumbnail, + updateFilePlacements, } from "@/service/content/content"; +import { getUserLevelForAssignments } from "@/service/task"; import { detailMedia } from "@/service/curated-content/curated-content"; import { Badge } from "@/components/ui/badge"; import { CloudUpload, MailIcon } from "lucide-react"; @@ -57,6 +60,7 @@ import { error, loading } from "@/lib/swal"; import { useTranslations } from "next-intl"; import dynamic from "next/dynamic"; import { htmlToString } from "@/utils/globals"; +import { v4 as uuidv4 } from "uuid"; const videoSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -97,6 +101,35 @@ type Option = { name: string; }; +type PlacementType = "all" | "mabes" | "wilayah" | "polda" | "satker" | "international"; + +interface FilePlacement { + id: string; + placements: PlacementType[]; +} + +interface TempFileItem { + id: string; + fileName: string; + url: string; + thumbnailFileUrl: string; + placements: string; + customLocationPlacements: string; +} + +interface Destination { + id: number; + name: string; + levelNumber: number; + subDestination: SubDestination[]; +} + +interface SubDestination { + id: number; + name: string; + levelNumber: number; +} + const CustomEditor = dynamic( () => { return import("@/components/editor/custom-editor"); @@ -132,17 +165,42 @@ export default function FormVideoUpdate() { const [thumbsSwiper, setThumbsSwiper] = useState(null); const [files, setFiles] = useState([]); const [selectedTarget, setSelectedTarget] = useState(""); - const [unitSelection, setUnitSelection] = useState({ - allUnit: false, - mabes: false, - polda: false, - polres: false, - }); const [publishedFor, setPublishedFor] = useState([]); const inputRef = useRef(null); const [selectedOptions, setSelectedOptions] = useState<{ [fileId: number]: string[]; }>({}); + const [fileUnitSelections, setFileUnitSelections] = useState<{ + [fileId: string]: { + semua: boolean; + nasional: boolean; + wilayah: boolean; + international: boolean; + polda: boolean; + satker: boolean; + }; + }>({}); + 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>(new Set()); + const [fileCheckedLevels, setFileCheckedLevels] = useState<{ + [fileId: string]: Set; + }>({}); + const [isUpdatingFromMainCheckbox, setIsUpdatingFromMainCheckbox] = useState(false); + const [mainCheckboxChangeType, setMainCheckboxChangeType] = useState(null); + const [filePlacements, setFilePlacements] = useState<{ + [fileId: string]: PlacementType[]; + }>({}); + const [tempFile, setTempFile] = useState(null); const options: Option[] = [ { id: "all", name: "SEMUA" }, @@ -156,7 +214,10 @@ export default function FormVideoUpdate() { const { getRootProps, getInputProps } = useDropzone({ onDrop: (acceptedFiles) => { - setFiles(acceptedFiles.map((file) => Object.assign(file))); + setFiles(acceptedFiles.map((file) => Object.assign(file, { + id: uuidv4(), + preview: URL.createObjectURL(file) + }))); }, accept: { "video/*": [], @@ -203,6 +264,36 @@ export default function FormVideoUpdate() { initState(); }, []); + useEffect(() => { + const fetchPoldaPolres = async () => { + try { + setIsLoading(true); + const response = await getUserLevelForAssignments(); + if (response?.data?.data) { + setListDest(response.data.data.list); + } + } catch (error) { + console.error("Error fetching user levels:", error); + } finally { + setIsLoading(false); + } + }; + + fetchPoldaPolres(); + }, []); + + useEffect(() => { + if (isUpdatingFromMainCheckbox && mainCheckboxChangeType) { + syncModalWithMainCheckbox(); + setIsUpdatingFromMainCheckbox(false); + setMainCheckboxChangeType(null); + } + }, [isUpdatingFromMainCheckbox, mainCheckboxChangeType]); + + useEffect(() => { + updateMainCheckboxFromModalLegacy(); + }, [checkedLevels]); + const handleAddTag = (e: React.KeyboardEvent) => { if (e.key === "Enter" && e.currentTarget.value.trim()) { e.preventDefault(); @@ -274,13 +365,43 @@ export default function FormVideoUpdate() { if (details?.files) { setFiles(details.files); - const initialOptions: { [key: number]: string[] } = {}; + + // Initialize filePlacements + const initialFilePlacements: { [key: string]: PlacementType[] } = {}; details.files.forEach((file: any) => { if (file.placements) { - initialOptions[file.id] = mapPlacementsToOptions(file.placements); + const placements = file.placements.split(",").map((p: string) => p.trim() as PlacementType); + initialFilePlacements[file.id] = placements; } }); - setSelectedOptions(initialOptions); + setFilePlacements(initialFilePlacements); + + // Initialize fileCheckedLevels + const initialFileCheckedLevels: { [key: string]: Set } = {}; + details.files.forEach((file: any) => { + if (file.customLocationPlacements) { + const levelIds = file.customLocationPlacements.split(",").map((id: string) => parseInt(id.trim())); + initialFileCheckedLevels[file.id] = new Set(levelIds); + } + }); + setFileCheckedLevels(initialFileCheckedLevels); + + // Initialize fileUnitSelections + const initialFileUnitSelections: { [key: string]: any } = {}; + details.files.forEach((file: any) => { + if (file.placements) { + const placements = file.placements.split(",").map((p: string) => p.trim()); + initialFileUnitSelections[file.id] = { + semua: placements.includes("all"), + nasional: placements.includes("mabes"), + wilayah: placements.includes("wilayah") || placements.includes("polda") || placements.includes("satker"), + international: placements.includes("international"), + polda: placements.includes("polda"), + satker: placements.includes("satker"), + }; + } + }); + setFileUnitSelections(initialFileUnitSelections); } if (details?.publishedFor) { @@ -312,29 +433,206 @@ export default function FormVideoUpdate() { initState(); }, [refresh, setValue]); - const mapPlacementsToOptions = (placements: string): string[] => { - const mapping: Record = { - all: "all", - mabes: "nasional", - polda: "wilayah", - polres: "internasional", - }; + const updateMainCheckboxFromModalLegacy = () => { + const checkedPoldaCount = listDest.filter( + (item) => item.levelNumber === 2 && item.name !== "SATKER POLRI" && checkedLevels.has(item.id) + ).length; + const hasSelectedPolda = checkedPoldaCount > 0; + const allPoldaChecked = checkedPoldaCount === listDest.filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI").length; - // Jika placements hanya "all", langsung aktifkan semua checkbox - if (placements.trim() === "all") { - return ["all", "nasional", "wilayah", "internasional"]; + const checkedSatkerCount = listDest.filter( + (item) => item.levelNumber === 2 && item.name === "SATKER POLRI" && checkedLevels.has(item.id) + ).length; + const hasSelectedSatker = checkedSatkerCount > 0; + const allSatkerChecked = checkedSatkerCount === listDest.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI").length; + + setUnitSelection(prev => ({ + ...prev, + polda: hasSelectedPolda, + satker: hasSelectedSatker, + wilayah: hasSelectedPolda || hasSelectedSatker, + })); + }; + + const syncModalWithMainCheckbox = () => { + if (mainCheckboxChangeType === "wilayah_checked") { + const poldaIds = listDest + .filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI") + .map(item => item.id); + const satkerIds = listDest + .filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI") + .map(item => item.id); + const allSatkerSubIds = listDest + .filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI") + .flatMap(item => item.subDestination.map(sub => sub.id)); + + setCheckedLevels(prev => { + const newSet = new Set(prev); + [...poldaIds, ...satkerIds, ...allSatkerSubIds].forEach(id => newSet.add(id)); + return newSet; + }); + } else if (mainCheckboxChangeType === "wilayah_unchecked") { + const poldaIds = listDest + .filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI") + .map(item => item.id); + const satkerIds = listDest + .filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI") + .map(item => item.id); + const allSatkerSubIds = listDest + .filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI") + .flatMap(item => item.subDestination.map(sub => sub.id)); + + setCheckedLevels(prev => { + const newSet = new Set(prev); + [...poldaIds, ...satkerIds, ...allSatkerSubIds].forEach(id => newSet.delete(id)); + return newSet; + }); + } else if (mainCheckboxChangeType === "polda_checked") { + const poldaIds = listDest + .filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI") + .map(item => item.id); + setCheckedLevels(prev => { + const newSet = new Set(prev); + poldaIds.forEach(id => newSet.add(id)); + return newSet; + }); + } else if (mainCheckboxChangeType === "polda_unchecked") { + const poldaIds = listDest + .filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI") + .map(item => item.id); + setCheckedLevels(prev => { + const newSet = new Set(prev); + poldaIds.forEach(id => newSet.delete(id)); + return newSet; + }); + } else if (mainCheckboxChangeType === "satker_checked") { + const satkerIds = listDest + .filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI") + .map(item => item.id); + const allSatkerSubIds = listDest + .filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI") + .flatMap(item => item.subDestination.map(sub => sub.id)); + setCheckedLevels(prev => { + const newSet = new Set(prev); + [...satkerIds, ...allSatkerSubIds].forEach(id => newSet.add(id)); + return newSet; + }); + } else if (mainCheckboxChangeType === "satker_unchecked") { + const satkerIds = listDest + .filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI") + .map(item => item.id); + const allSatkerSubIds = listDest + .filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI") + .flatMap(item => item.subDestination.map(sub => sub.id)); + setCheckedLevels(prev => { + const newSet = new Set(prev); + [...satkerIds, ...allSatkerSubIds].forEach(id => newSet.delete(id)); + return newSet; + }); } + }; - const options = placements - .split(",") - .map((p) => mapping[p.trim()]) - .filter(Boolean); + const handleFileUnitChange = (fileId: string, key: string, value: boolean) => { + setFileUnitSelections(prev => { + const currentSelection = prev[fileId] || { + semua: false, + nasional: false, + wilayah: false, + international: false, + polda: false, + satker: false, + }; - const allSelected = ["nasional", "wilayah", "internasional"].every((opt) => - options.includes(opt) - ); + const newSelection = { ...currentSelection, [key]: value }; - return allSelected ? ["all", ...options] : options; + if (key === "wilayah" && value) { + newSelection.polda = true; + newSelection.satker = true; + + // Update fileCheckedLevels for wilayah + setFileCheckedLevels(prevLevels => { + const currentFileLevels = prevLevels[fileId] || new Set(); + const newFileLevels = new Set(currentFileLevels); + + // Add all POLDA items + listDest.forEach(item => { + if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { + newFileLevels.add(item.id); + } + }); + + // Add SATKER POLRI items and their sub-destinations + listDest.forEach(item => { + if (item.levelNumber === 2 && item.name === "SATKER POLRI") { + newFileLevels.add(item.id); + item.subDestination.forEach(satkerItem => { + newFileLevels.add(satkerItem.id); + }); + } + }); + + return { ...prevLevels, [fileId]: newFileLevels }; + }); + } else if (key === "wilayah" && !value) { + newSelection.polda = false; + newSelection.satker = false; + + // Clear fileCheckedLevels for wilayah + setFileCheckedLevels(prevLevels => { + const newFileLevels = new Set(); + return { ...prevLevels, [fileId]: newFileLevels }; + }); + } else if (key === "semua") { + newSelection.nasional = value; + newSelection.wilayah = value; + newSelection.international = value; + newSelection.polda = value; + newSelection.satker = value; + } + + return { ...prev, [fileId]: newSelection }; + }); + + // Update filePlacements + setFilePlacements(prev => { + const currentPlacements = prev[fileId] || []; + let newPlacements = [...currentPlacements]; + + if (key === "semua" && value) { + newPlacements = ["all", "mabes", "wilayah", "polda", "satker", "international"]; + } else if (key === "semua" && !value) { + newPlacements = []; + } else if (key === "nasional" && value) { + if (!newPlacements.includes("mabes")) newPlacements.push("mabes"); + } else if (key === "nasional" && !value) { + newPlacements = newPlacements.filter(p => p !== "mabes"); + } else if (key === "wilayah" && value) { + if (!newPlacements.includes("wilayah")) newPlacements.push("wilayah"); + if (!newPlacements.includes("polda")) newPlacements.push("polda"); + if (!newPlacements.includes("satker")) newPlacements.push("satker"); + } else if (key === "wilayah" && !value) { + newPlacements = newPlacements.filter(p => !["wilayah", "polda", "satker"].includes(p)); + } else if (key === "international" && value) { + if (!newPlacements.includes("international")) newPlacements.push("international"); + } else if (key === "international" && !value) { + newPlacements = newPlacements.filter(p => p !== "international"); + } else if (key === "polda" && value) { + if (!newPlacements.includes("polda")) newPlacements.push("polda"); + } else if (key === "polda" && !value) { + newPlacements = newPlacements.filter(p => p !== "polda"); + } else if (key === "satker" && value) { + if (!newPlacements.includes("satker")) newPlacements.push("satker"); + } else if (key === "satker" && !value) { + newPlacements = newPlacements.filter(p => p !== "satker"); + } + + // Remove "all" if any individual option is unchecked + if (newPlacements.includes("all") && !value && key !== "semua") { + newPlacements = newPlacements.filter(p => p !== "all"); + } + + return { ...prev, [fileId]: newPlacements }; + }); }; const handleCheckboxChange = (id: string) => { @@ -354,6 +652,192 @@ export default function FormVideoUpdate() { } }; + const handleFileCheckboxChangePlacement = (fileId: string, poldaItem: Destination, isChecked: boolean) => { + setFileCheckedLevels(prev => { + const currentFileLevels = prev[fileId] || new Set(); + const newFileLevels = new Set(currentFileLevels); + + if (isChecked) { + newFileLevels.add(poldaItem.id); + // Add all sub-destinations for SATKER POLRI + if (poldaItem.name === "SATKER POLRI") { + poldaItem.subDestination.forEach((satkerItem: SubDestination) => { + newFileLevels.add(satkerItem.id); + }); + } + } else { + newFileLevels.delete(poldaItem.id); + // Remove all sub-destinations for SATKER POLRI + if (poldaItem.name === "SATKER POLRI") { + poldaItem.subDestination.forEach((satkerItem: SubDestination) => { + newFileLevels.delete(satkerItem.id); + }); + } + } + + return { ...prev, [fileId]: newFileLevels }; + }); + + // Update fileUnitSelections based on checked levels + const updatedFileLevels = fileCheckedLevels[fileId] || new Set(); + const hasPolda = listDest.some(item => + item.levelNumber === 2 && + item.name !== "SATKER POLRI" && + updatedFileLevels.has(item.id) + ); + const hasSatker = listDest.some(item => + item.levelNumber === 2 && + item.name === "SATKER POLRI" && + updatedFileLevels.has(item.id) + ); + + setFileUnitSelections(prev => ({ + ...prev, + [fileId]: { + ...prev[fileId], + polda: hasPolda, + satker: hasSatker, + wilayah: hasPolda || hasSatker, + } + })); + }; + + const updateMainCheckboxFromModal = (fileId: string) => { + const fileLevels = fileCheckedLevels[fileId] || new Set(); + const hasPolda = listDest.some(item => + item.levelNumber === 2 && + item.name !== "SATKER POLRI" && + fileLevels.has(item.id) + ); + const hasSatker = listDest.some(item => + item.levelNumber === 2 && + item.name === "SATKER POLRI" && + fileLevels.has(item.id) + ); + + setFileUnitSelections(prev => ({ + ...prev, + [fileId]: { + ...prev[fileId], + polda: hasPolda, + satker: hasSatker, + wilayah: hasPolda || hasSatker, + } + })); + }; + + const toggleExpand = (poldaId: number) => { + setExpandedPolda(prev => { + const newSet = new Set(prev); + if (newSet.has(poldaId)) { + newSet.delete(poldaId); + } else { + newSet.add(poldaId); + } + return newSet; + }); + }; + + const handleSelectAllSubItems = (fileId: string, poldaItem: Destination) => { + const fileLevels = fileCheckedLevels[fileId] || new Set(); + const allSubItemsSelected = poldaItem.subDestination.every(subItem => + fileLevels.has(subItem.id) + ); + + setFileCheckedLevels(prev => { + const currentFileLevels = prev[fileId] || new Set(); + const newFileLevels = new Set(currentFileLevels); + + if (allSubItemsSelected) { + // Unselect all sub-items + poldaItem.subDestination.forEach(subItem => { + newFileLevels.delete(subItem.id); + }); + } else { + // Select all sub-items + poldaItem.subDestination.forEach(subItem => { + newFileLevels.add(subItem.id); + }); + } + + return { ...prev, [fileId]: newFileLevels }; + }); + }; + + const getPlacement = (fileId?: string): string => { + if (fileId && filePlacements[fileId]) { + const placements = filePlacements[fileId]; + let nowArr = placements.join(","); + nowArr = nowArr?.replaceAll("all", "all"); + nowArr = nowArr?.replaceAll("mabes", "mabes"); + nowArr = nowArr?.replaceAll("wilayah", "polda"); + nowArr = nowArr?.replaceAll("polda", "polda"); + nowArr = nowArr?.replaceAll("satker", "satker"); + nowArr = nowArr?.replaceAll("international", "international"); + return nowArr; + } + return ""; + }; + + const setupPlacement = (fileId: string, placement: string, isChecked: boolean) => { + setFilePlacements(prev => { + const currentPlacements = prev[fileId] || []; + let temp = { ...prev }; + + if (isChecked) { + if (placement === "all") { + temp[fileId] = ["all", "mabes", "wilayah", "polda", "satker", "international"]; + } else if (placement === "wilayah") { + temp[fileId] = [...currentPlacements, "wilayah", "polda", "satker"]; + } else if (placement === "polda") { + temp[fileId] = [...currentPlacements, "polda"]; + } else if (placement === "satker") { + temp[fileId] = [...currentPlacements, "satker"]; + } else { + temp[fileId] = [...currentPlacements, placement as PlacementType]; + } + } else { + if (placement === "all") { + temp[fileId] = []; + } else if (placement === "wilayah") { + temp[fileId] = currentPlacements.filter(p => !["wilayah", "polda", "satker"].includes(p)); + } else if (placement === "polda") { + temp[fileId] = currentPlacements.filter(p => p !== "polda"); + } else if (placement === "satker") { + temp[fileId] = currentPlacements.filter(p => p !== "satker"); + } else { + temp[fileId] = currentPlacements.filter(p => p !== placement); + } + } + + return temp; + }); + }; + + const updateModalChecklistLevels = (fileId: string) => { + const fileLevels = fileCheckedLevels[fileId] || new Set(); + const hasPolda = listDest.some(item => + item.levelNumber === 2 && + item.name !== "SATKER POLRI" && + fileLevels.has(item.id) + ); + const hasSatker = listDest.some(item => + item.levelNumber === 2 && + item.name === "SATKER POLRI" && + fileLevels.has(item.id) + ); + + setFileUnitSelections(prev => ({ + ...prev, + [fileId]: { + ...prev[fileId], + polda: hasPolda, + satker: hasSatker, + wilayah: hasPolda || hasSatker, + } + })); + }; + // const save = async (data: VideoSchema) => { // loading(); // const finalTags = tags.join(", "); @@ -441,6 +925,15 @@ export default function FormVideoUpdate() { return false; } + // Update file placements + if (files.length > 0) { + files.forEach((file: any) => { + if (file.id) { + updateFilePlacements(getPlacement(file.id)); + } + }); + } + if (selectedFiles.length > 0) { const thumbnail = selectedFiles[0]; const formMedia = new FormData(); @@ -638,37 +1131,6 @@ export default function FormVideoUpdate() { )); - const handleCheckboxChangeImage = (fileId: number, value: string) => { - setSelectedOptions((prev: any) => { - const currentSelections = prev[fileId] || []; - if (value === "all") { - // If "all" is clicked, toggle all options - if (currentSelections.includes("all")) { - return { ...prev, [fileId]: [] }; // Deselect all - } - return { - ...prev, - [fileId]: ["all", "nasional", "wilayah", "internasional"], - }; // Select all - } else { - // If any other checkbox is clicked, toggle that checkbox - const updatedSelections = currentSelections.includes(value) - ? currentSelections.filter((option: any) => option !== value) - : [...currentSelections, value]; - - // If all individual options are selected, include "all" automatically - const isAllSelected = ["nasional", "wilayah", "internasional"].every( - (opt) => updatedSelections.includes(opt) - ); - return { - ...prev, - [fileId]: isAllSelected - ? ["all", ...updatedSelections] - : updatedSelections.filter((opt: any) => opt !== "all"), - }; - } - }); - }; function success() { MySwal.fire({ @@ -885,79 +1347,137 @@ export default function FormVideoUpdate() { })} -
- -
-
- -
-
- -
-
- +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + + + + + + Daftar Wilayah POLDA dan SATKER + +
+ {listDest?.filter((item) => item.levelNumber === 2) + .map((poldaItem) => ( +
+
+ + handleFileCheckboxChangePlacement(file.id, poldaItem, checked as boolean) + } + /> + + {poldaItem.name === "SATKER POLRI" && poldaItem.subDestination.length > 0 && ( + + )} +
+ {poldaItem.name === "SATKER POLRI" && expandedPolda.has(poldaItem.id) && ( +
+
+ +
+ {poldaItem.subDestination.map((satkerItem) => ( +
+ { + setFileCheckedLevels(prev => { + const currentFileLevels = prev[file.id] || new Set(); + const newFileLevels = new Set(currentFileLevels); + if (checked) { + newFileLevels.add(satkerItem.id); + } else { + newFileLevels.delete(satkerItem.id); + } + return { ...prev, [file.id]: newFileLevels }; + }); + updateMainCheckboxFromModal(file.id); + }} + /> + +
+ ))} +
+ )} +
+ ))} +
+
+
+