From e5a2fc2bf1efcf9f3a60081a2633b8a3a3dd885c Mon Sep 17 00:00:00 2001 From: Sabda Yagra Date: Fri, 22 Aug 2025 16:23:37 +0700 Subject: [PATCH] fix: placement in approval content --- components/form/content/audio-detail-form.tsx | 1281 +++++++++++------ components/form/content/teks-detail-form.tsx | 1281 +++++++++++------ components/form/content/video-detail-form.tsx | 1229 +++++++++++----- 3 files changed, 2602 insertions(+), 1189 deletions(-) diff --git a/components/form/content/audio-detail-form.tsx b/components/form/content/audio-detail-form.tsx index e9d5120b..d9c6c794 100644 --- a/components/form/content/audio-detail-form.tsx +++ b/components/form/content/audio-detail-form.tsx @@ -51,6 +51,7 @@ import { DialogContent, DialogTitle, DialogTrigger, + DialogClose, } from "@/components/ui/dialog"; import { Textarea } from "@/components/ui/textarea"; import { loading } from "@/config/swal"; @@ -180,6 +181,83 @@ export default function FormAudioDetail() { const [isLoading, setIsLoading] = useState(false); const [listDest, setListDest] = useState([]); const [checkedLevels, setCheckedLevels] = useState(new Set()); + // State untuk setiap file secara individual - checklist levels + const [fileCheckedLevels, setFileCheckedLevels] = useState< + Array> + >([]); + // State untuk setiap file secara individual + const [fileUnitSelections, setFileUnitSelections] = useState< + Array<{ + semua: boolean; + nasional: boolean; + wilayah: boolean; + international: boolean; + polda: boolean; + polres: boolean; + satker: boolean; + }> + >([]); + + // 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.polres = value; + currentSelection.satker = value; + } else { + // Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist + if (key === "polres" && value) { + const currentFileCheckedLevels = fileCheckedLevels[fileIndex]; + const hasSelectedPolda = + currentFileCheckedLevels && + listDest.some( + (item: any) => + item.levelNumber === 2 && + item.name !== "SATKER POLRI" && + currentFileCheckedLevels.has(Number(item.id)) + ); + + if (!hasSelectedPolda) { + alert( + "Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES." + ); + return prev; // Batalkan perubahan + } + } + + // Update salah satu saja + currentSelection[key] = value; + + // Cek apakah semua selain "semua" sudah dicentang + const allChecked = [ + "nasional", + "wilayah", + "international", + "polda", + "polres", + "satker", + ].every((k) => currentSelection[k as keyof typeof unitSelection]); + + currentSelection.semua = allChecked; + } + + newSelections[fileIndex] = currentSelection; + return newSelections; + }); + }; const toggleExpand = (id: number) => { setExpandedPolda((prev) => ({ @@ -555,37 +633,37 @@ export default function FormAudioDetail() { setRejectedFiles(rejects); } - const setupPlacement = ( - index: number, - placement: string, - checked: boolean - ) => { - let temp = [...filePlacements]; - if (checked) { - if (placement === "all") { - temp[index] = ["all", "mabes", "polda", "international"]; - } else { - const now = temp[index]; - now?.push(placement); - if (now?.length === 3 && !now?.includes("all")) { - now?.push("all"); - } - temp[index] = now; - } - } else { - if (placement === "all") { - temp[index] = []; - } else { - const now = temp[index].filter((a) => a !== placement); - temp[index] = now; - if (now?.length === 3 && now?.includes("all")) { - const newData = now.filter((b) => b !== "all"); - temp[index] = newData; - } - } - } - setFilePlacements(temp); - }; + // const setupPlacement = ( + // index: number, + // placement: string, + // checked: boolean + // ) => { + // let temp = [...filePlacements]; + // if (checked) { + // if (placement === "all") { + // temp[index] = ["all", "mabes", "polda", "international"]; + // } else { + // const now = temp[index]; + // now?.push(placement); + // if (now?.length === 3 && !now?.includes("all")) { + // now?.push("all"); + // } + // temp[index] = now; + // } + // } else { + // if (placement === "all") { + // temp[index] = []; + // } else { + // const now = temp[index].filter((a) => a !== placement); + // temp[index] = now; + // if (now?.length === 3 && now?.includes("all")) { + // const newData = now.filter((b) => b !== "all"); + // temp[index] = newData; + // } + // } + // } + // setFilePlacements(temp); + // }; const handleMain = ( type: string, @@ -623,6 +701,334 @@ export default function FormAudioDetail() { }); }; + const setupPlacement = ( + index: number, + placement: string, + checked: boolean + ) => { + let temp = [...filePlacements]; + if (checked) { + if (placement === "all") { + temp[index] = ["all", "mabes", "polda", "international"]; + } else if (placement === "satker") { + // Ketika satker di-checklist, HANYA tambahkan satker saja + // JANGAN otomatis checklist polres + 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); + } + // Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist + // JANGAN include satker dalam perhitungan auto "all" + 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] = []; + } else { + const now = temp[index]?.filter((a) => a !== placement); + console.log("now", now); + 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); + }; + + 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 === "polres") { + // Checklist POLRES hanya dari POLDA yang sudah ter-checklist + listDest.forEach((item: any) => { + if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { + // Hanya checklist POLRES jika POLDA-nya sudah ter-checklist + if (currentFileLevels.has(Number(item.id))) { + if (item.subDestination) { + item.subDestination.forEach((polres: any) => { + currentFileLevels.add(Number(polres.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 dan POLRES di bawahnya + listDest.forEach((item: any) => { + if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { + currentFileLevels.delete(Number(item.id)); + if (item.subDestination) { + item.subDestination.forEach((polres: any) => { + currentFileLevels.delete(Number(polres.id)); + }); + } + } + }); + } else if (placement === "polres") { + // Unchecklist semua POLRES + listDest.forEach((item: any) => { + if (item.subDestination && item.name !== "SATKER POLRI") { + item.subDestination.forEach((polres: any) => { + currentFileLevels.delete(Number(polres.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 [portraitMap, setPortraitMap] = useState({}); + + const handleImageLoad = (e: any, index: number) => { + const { naturalWidth, naturalHeight } = e.target; + const isPortrait = naturalHeight > naturalWidth; + + setPortraitMap((prev: any) => ({ + ...prev, + [index]: isPortrait, + })); + }; + + // 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); + + // Hitung total POLRES yang ada dari POLDA yang ter-checklist + const totalPolresFromCheckedPolda = listDest.reduce( + (total: number, item: any) => { + if ( + item.subDestination && + item.name !== "SATKER POLRI" && + currentFileLevels.has(Number(item.id)) + ) { + return total + item.subDestination.length; + } + return total; + }, + 0 + ); + + // Hitung berapa banyak POLRES yang ter-checklist + const checkedPolresCount = listDest.reduce((total: number, item: any) => { + if (item.subDestination && item.name !== "SATKER POLRI") { + // Hanya hitung sub-item dari POLDA (bukan dari SATKER POLRI) + return ( + total + + item.subDestination.filter((sub: any) => + currentFileLevels.has(Number(sub.id)) + ).length + ); + } + 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; + // POLRES aktif jika ada minimal 1 POLRES ter-checklist + currentSelection.polres = checkedPolresCount > 0; + currentSelection.satker = Boolean(isSatkerChecked); + + newSelections[fileIndex] = currentSelection; + return newSelections; + }); + }; + + // Fungsi untuk menangani "Pilih Semua" sub-items di bawah POLDA + 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 POLDA 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; + }); + }; + return (
{detail !== undefined ? ( @@ -844,402 +1250,471 @@ export default function FormAudioDetail() { )} */} - - - - {t("leave-comment", { defaultValue: "Leave Comment" })} + + + + {t("leave-comment", { + defaultValue: "Kelola Persetujuan Konten", + })} - {status == "2" - ? files?.map((file, index) => ( + +
+ {status == "2" && + files?.map((file, index) => (
- {/* */} - - - {" "} -
-
- {file.fileName} - - handleDeleteFileApproval(file.id) - } - > - - + {/* Header File */} +
+
+
+ {/* {`files-${index handleImageLoad(e, index)} + className={`h-[80px] object-cover ${ + portraitMap[index] ? "w-auto" : "!w-[120px]" + }`} + /> */} + + + +
+
+

+ File {index + 1} +

+

+ {file.fileName} +

+
-
- {/* --- Checkbox utama --- */} -
- {[ - "semua", - "nasional", - "wilayah", - "international", - ].map((key, index) => ( -
- { - handleUnitChange( - key as keyof typeof unitSelection, - value as boolean - ); - setupPlacement( - index, - key, - Boolean(value) - ); - }} - /> - -
- ))} + +
+ + {/* Section Pengaturan Distribusi */} +
+
+ + Pengaturan Distribusi +
+ + {/* Checkbox Tingkat Utama */} +
+
+

+ Tingkat Distribusi: +

+
+ {[ + { 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) + ); + }} + /> + +
+ ))} +
- {/* --- Kalau wilayah dicentang baru tampilkan detail --- */} - {unitSelection.wilayah && ( -
-
- {["polda", "polres", "satker"].map( - (key, index) => ( -
- { - handleUnitChange( - key as keyof typeof unitSelection, - value as boolean - ); - setupPlacement( - index, - key, - Boolean(value) - ); - }} - /> - -
- ) - )} -
+ {/* Detail Wilayah */} + {fileUnitSelections[index]?.wilayah && ( +
+

+ Detail Wilayah: +

- {/* --- Custom Button + Dialog --- */} - - - - - - - - Daftar Wilayah Polda dan Polres - - -
- {listDest.map((polda: any) => { - const poldaChecked = - unitSelection.polda; - const polresChecked = - unitSelection.polres; - const isPoldaDisabled = poldaChecked; - const isPolresDisabled = - polresChecked; + { + handleFileUnitChange( + index, + item.key as keyof typeof unitSelection, + value as boolean + ); + setupPlacement( + index, + item.key, + Boolean(value) + ); + }} + /> + +
+ ))} - return ( -
- - - {expandedPolda[polda.id] && ( -
- {polda?.subDestination?.map( - (polres: any) => ( - - ) + {/* Tombol Kustom sejajar dengan checkbox */} +
+ + + + + + + + Daftar Wilayah POLDA dan POLRES + + +
+ {listDest.map((polda: any) => ( +
+ {/* Header POLDA */} +
+ + {polda.subDestination && ( + )}
- )} -
- ); - })} -
-
-
+ + {/* Sub-items */} + {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) => ( + + ) + )} +
+
+ )} +
+ ))} +
+
+ + + + + + +
+ +
+
+
)}
- {/* {isUserMabesApprover && ( -
-
- - setupPlacement(index, "all", Boolean(e)) - } - /> - -
-
- - setupPlacement(index, "mabes", Boolean(e)) - } - /> - -
-
- - setupPlacement(index, "polda", Boolean(e)) - } - /> - -
- -
- - setupPlacement( - index, - "international", - Boolean(e) - ) - } - /> - -
-
- )} */}
- )) - : ""} -
-