diff --git a/components/form/content/image-detail-form.tsx b/components/form/content/image-detail-form.tsx index 21c4c98b..73b97aee 100644 --- a/components/form/content/image-detail-form.tsx +++ b/components/form/content/image-detail-form.tsx @@ -20,7 +20,7 @@ import { 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 { @@ -53,6 +53,7 @@ import { DialogContent, DialogTitle, DialogTrigger, + DialogClose, } from "@/components/ui/dialog"; import { Textarea } from "@/components/ui/textarea"; import { close, loading, successCallback } from "@/config/swal"; @@ -161,6 +162,21 @@ export default function FormImageDetail() { const [thumbsSwiper, setThumbsSwiper] = useState(null); const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); const [approval, setApproval] = useState(); + // State untuk setiap file secara individual + const [fileUnitSelections, setFileUnitSelections] = useState>([]); + + // State untuk setiap file secara individual - checklist levels + const [fileCheckedLevels, setFileCheckedLevels] = useState>>([]); + + // State global untuk kompatibilitas (akan dihapus nanti) const [unitSelection, setUnitSelection] = useState({ semua: false, nasional: false, @@ -255,12 +271,12 @@ export default function FormImageDetail() { // useEffect untuk update checkbox utama ketika pilihan modal berubah useEffect(() => { if (!isUpdatingFromMainCheckbox && listDest.length > 0) { - updateMainCheckboxFromModal(); + updateMainCheckboxFromModalLegacy(); } }, [checkedLevels, isUpdatingFromMainCheckbox]); - // Fungsi untuk update checkbox utama berdasarkan checkbox modal - const updateMainCheckboxFromModal = () => { + // 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) => @@ -406,6 +422,63 @@ export default function FormImageDetail() { } }; + // 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; + }); + }; + + // Fungsi lama untuk kompatibilitas (akan dihapus nanti) const handleUnitChange = ( key: keyof typeof unitSelection, value: boolean @@ -497,6 +570,146 @@ export default function FormImageDetail() { ); }; + // 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 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; + }); + }; + + // 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 lama untuk kompatibilitas (akan dihapus nanti) const handleCheckboxChangePlacement = (levelId: number) => { setCheckedLevels((prev: Set) => { const updatedLevels = new Set(prev); @@ -570,10 +783,28 @@ export default function FormImageDetail() { const setupPlacementCheck = (length: number) => { const temp = []; + const unitSelections = []; + const checkedLevelsArray = []; + for (let i = 0; i < length; i++) { temp.push([]); + // Inisialisasi state untuk setiap file + unitSelections.push({ + semua: false, + nasional: false, + wilayah: false, + international: false, + polda: false, + polres: false, + satker: false, + }); + // Inisialisasi checkedLevels untuk setiap file + checkedLevelsArray.push(new Set()); } + setFilePlacements(temp); + setFileUnitSelections(unitSelections); + setFileCheckedLevels(checkedLevelsArray); }; useEffect(() => { @@ -673,12 +904,20 @@ export default function FormImageDetail() { }; async function save() { + // Gabungkan semua checkedLevels dari semua file + const allCheckedLevels = new Set(); + fileCheckedLevels.forEach((fileLevels) => { + fileLevels.forEach((levelId) => { + allCheckedLevels.add(levelId); + }); + }); + const data = { mediaUploadId: id, statusId: status, message: description, files: isUserMabesApprover ? getPlacement() : [], - customLocationPlacement: Array.from(checkedLevels).join(","), + customLocationPlacement: Array.from(allCheckedLevels).join(","), }; setModalOpen(false); loading(); @@ -756,6 +995,92 @@ export default function FormImageDetail() { } } 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 === "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; + }); }; function handleDeleteFileApproval(id: number) { @@ -1111,445 +1436,309 @@ export default function FormImageDetail() { )} */} - - - - {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) => ( +
+ {/* Header File */} +
+
+
{`files-${index handleImageLoad(e, index)} - className={`h-[100px] object-cover ${ - portraitMap[index] ? "w-auto" : "!w-[200px]" + className={`h-[80px] object-cover ${ + portraitMap[index] ? "w-auto" : "!w-[120px]" }`} />
-
-
- {file.fileName} - - handleDeleteFileApproval(file.id) - } - > - - +
+

File {index + 1}

+

{file.fileName}

+
+
+ +
+ + {/* 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)); + }} + /> + +
+ ))}
-
- {/* --- Checkbox utama --- */} -
+
+ + {/* Detail Wilayah */} + {fileUnitSelections[index]?.wilayah && ( +
+

Detail Wilayah:

+ + {/* Checkbox Sub-kategori dengan tombol Kustom sejajar */} +
{[ - "semua", - "nasional", - "wilayah", - "international", - ].map((key, index) => ( -
+ { key: "polda", label: "POLDA" }, + { key: "polres", label: "POLRES" }, + { key: "satker", label: "SATKER" }, + ].map((item, idx) => ( +
{ - handleUnitChange( - key as keyof typeof unitSelection, + handleFileUnitChange( + index, + item.key as keyof typeof unitSelection, value as boolean ); - setupPlacement( - index, - key, - Boolean(value) - ); + 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) - ); - }} - /> - -
- ) - )} -
- - {/* --- Custom Button + Dialog --- */} + + {/* Tombol Kustom sejajar dengan checkbox */} +
- - - - - Daftar Wilayah Polda dan Polres + + + + Daftar Wilayah POLDA dan POLRES -
+
{listDest.map((polda: any) => ( -
-
- +
+ {/* Header POLDA */} +
+ + {polda.subDestination && ( -
- - {expandedPolda[polda.id] && ( -
- - {polda?.subDestination?.map( - (polres: any) => ( - - ) - )} -
)}
+ + {/* 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) - ) - } - /> - - {wilayahPublish.polda && ( - - setSelectedPolda(data) - } - /> - )} -
- -
- - setupPlacement( - index, - "international", - Boolean(e) - ) - } - /> - -
- )} */} +
+ )} +
+
+
+ ))} +
+ + {/* Section Komentar */} +
+
+
+ +