diff --git a/app/[locale]/(protected)/contributor/schedule/calendar-polri/component/columns.tsx b/app/[locale]/(protected)/contributor/schedule/calendar-polri/component/columns.tsx index c0672f25..4d2a9f23 100644 --- a/app/[locale]/(protected)/contributor/schedule/calendar-polri/component/columns.tsx +++ b/app/[locale]/(protected)/contributor/schedule/calendar-polri/component/columns.tsx @@ -101,10 +101,8 @@ const useTableColumns = () => { enableHiding: false, cell: ({ row }) => { const MySwal = withReactContent(Swal); - const levelNumber = Number(getCookiesDecrypt("ulne")); // 1 = Mabes, 2 = Polda - const calendarOwnerLevel = Number(row.original.assignedToLevel); // dari API - const calendarOwner = row.original.assignedTo; // ID unit Polda/Mabes dari API - const myUnit = getCookiesDecrypt("unitId"); // misal ID unit Polda login + const levelNumber = Number(getCookiesDecrypt("ulne")); + const userId = Number(getCookiesDecrypt("uie")); async function doDelete(id: any) { const response = await deleteCalendar(id); @@ -143,29 +141,6 @@ const useTableColumns = () => { } }); }; - - // === RULE AKSI === - let canEdit = false; - let canDelete = false; - const canView = true; - - if (levelNumber === 1) { - // Mabes -> bebas - canEdit = true; - canDelete = true; - } else if (levelNumber === 2) { - // Polda - if (calendarOwnerLevel === 1) { - // kalender Mabes -> hanya view - canEdit = false; - canDelete = false; - } else if (calendarOwnerLevel === 2 && calendarOwner === myUnit) { - // kalender polda sendiri -> bisa edit/delete - canEdit = true; - canDelete = true; - } - } - return ( @@ -178,7 +153,7 @@ const useTableColumns = () => { - {canView && ( + @@ -187,9 +162,9 @@ const useTableColumns = () => { Detail - )} + - {canEdit && ( + {row.original.createdById === userId && ( @@ -200,7 +175,7 @@ const useTableColumns = () => { )} - {canDelete && ( + {row.original.createdById === userId && ( handleDeleteCalendars(row.original.id)} className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none" @@ -214,7 +189,7 @@ const useTableColumns = () => { ); }, }, - + // { // id: "actions", // accessorKey: "action", diff --git a/app/[locale]/(public)/faqs/page.tsx b/app/[locale]/(public)/faqs/page.tsx index 8acd56bb..65665137 100644 --- a/app/[locale]/(public)/faqs/page.tsx +++ b/app/[locale]/(public)/faqs/page.tsx @@ -2,6 +2,7 @@ import { Reveal } from "@/components/landing-page/Reveal"; import React, { useState } from "react"; import { useTranslations } from "next-intl"; +import Image from "next/image"; interface FAQItem { question: string; @@ -41,19 +42,41 @@ const FAQS: React.FC = () => { {/* Header */}
- Faqs -

Frequently Asked Questions

+ Faqs +

+ Frequently Asked Questions +

{/* FAQS Items */}
{faqs?.map((faq, index) => ( -
-
toggleFAQ(index)}> -

{faq.question}

- {openIndex === index ? "βˆ’" : "+"} +
+
toggleFAQ(index)} + > +

+ {faq.question} +

+ + {openIndex === index ? "βˆ’" : "+"} +
- {openIndex === index &&

{faq.answer}

} + {openIndex === index && ( +

+ {faq.answer} +

+ )}
))}
diff --git a/components/form/broadcast/content-blast-form.tsx b/components/form/broadcast/content-blast-form.tsx index 04df630d..3ba34239 100644 --- a/components/form/broadcast/content-blast-form.tsx +++ b/components/form/broadcast/content-blast-form.tsx @@ -27,7 +27,7 @@ import { saveMediaBlastCampaign, } from "@/service/broadcast/broadcast"; import { error } from "@/config/swal"; -import { useRouter } from "@/i18n/routing"; +import { Link, useRouter } from "@/i18n/routing"; import { useEffect, useRef, useState } from "react"; import { useParams } from "next/navigation"; @@ -78,6 +78,11 @@ const FormSchema = z.object({ }), }); +interface Campaign { + id: string; + name: string; +} + export default function ContentBlast(props: { type: string }) { const editor = useRef(null); const id = useParams()?.id; @@ -85,7 +90,7 @@ export default function ContentBlast(props: { type: string }) { const router = useRouter(); const { type } = props; - const [dataSelectCampaign, setDataSelectCampaign] = useState([]); + const [dataSelectCampaign, setDataSelectCampaign] = useState([]); const [openModal, setOpenModal] = useState(false); const form = useForm>({ @@ -295,9 +300,16 @@ export default function ContentBlast(props: { type: string }) { Untuk melihat Email Terkirim silahkan cek menu β€œSent”!
- + + + +
- - - - - Daftar Wilayah POLDA dan POLRES - - -
- {listDest.map((polda: any) => ( -
- {/* Header POLDA */} -
- - {polda.subDestination && ( - - )} -
+ {item.label} + +
+ ))} - {/* 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 ( - + {/* Tombol Kustom sejajar dengan checkbox */} +
+ + + + + + + + Daftar Wilayah POLDA dan POLRES + + +
+ {listDest.map((polda: any) => ( +
+ {/* Header POLDA */} +
+ + {polda.subDestination && ( +
-
- {polda.subDestination.map( - (sub: 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 ) - ) || false - } - onCheckedChange={() => - handleFileCheckboxChangePlacement( + ) + ); + return ( + + ); + })()} +
+
+ {polda.subDestination.map( + (sub: any) => ( + + ) + )} +
-
- )} -
- ))} -
-
- - - - - - -
- - + )} +
+ ))} +
+
+ + + + + + +
+ + +
- - )} + )} + - + ) : ( + "" + )} ))} diff --git a/components/form/content/image-detail-form.tsx b/components/form/content/image-detail-form.tsx index cabf9c4a..cad697bb 100644 --- a/components/form/content/image-detail-form.tsx +++ b/components/form/content/image-detail-form.tsx @@ -20,7 +20,6 @@ import { import { Checkbox } from "@/components/ui/checkbox"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; - import { Switch } from "@/components/ui/switch"; import Cookies from "js-cookie"; import { @@ -164,18 +163,28 @@ export default function FormImageDetail() { const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); const [approval, setApproval] = useState(); // State untuk setiap file secara individual - const [fileUnitSelections, setFileUnitSelections] = useState>([]); + const [fileUnitSelections, setFileUnitSelections] = useState< + Array<{ + semua: boolean; + nasional: boolean; + wilayah: boolean; + international: boolean; + polda: boolean; + polres: boolean; + satker: boolean; + }> + >([]); + + useEffect(() => { + if (Number(userLevelId) === 216 && Number(roleId) === 3) { + setIsUserMabesApprover(true); + } + }, [userLevelId, roleId]); // State untuk setiap file secara individual - checklist levels - const [fileCheckedLevels, setFileCheckedLevels] = useState>>([]); + const [fileCheckedLevels, setFileCheckedLevels] = useState< + Array> + >([]); // State global untuk kompatibilitas (akan dihapus nanti) const [unitSelection, setUnitSelection] = useState({ @@ -192,12 +201,16 @@ export default function FormImageDetail() { const [selectedTarget, setSelectedTarget] = useState(""); const [files, setFiles] = useState([]); const [rejectedFiles, setRejectedFiles] = useState([]); - const [expandedPolda, setExpandedPolda] = useState>({}); - + const [expandedPolda, setExpandedPolda] = useState>( + {} + ); + // State untuk melacak apakah perubahan berasal dari checkbox utama - const [isUpdatingFromMainCheckbox, setIsUpdatingFromMainCheckbox] = useState(false); + const [isUpdatingFromMainCheckbox, setIsUpdatingFromMainCheckbox] = + useState(false); // State untuk melacak jenis perubahan spesifik - const [mainCheckboxChangeType, setMainCheckboxChangeType] = useState(""); + const [mainCheckboxChangeType, setMainCheckboxChangeType] = + useState(""); const [wilayahPublish, setWilayahPublish] = React.useState({ semua: false, nasional: false, @@ -264,7 +277,11 @@ export default function FormImageDetail() { // useEffect untuk sinkronisasi checkbox modal dengan checkbox utama useEffect(() => { - if (listDest.length > 0 && isUpdatingFromMainCheckbox && mainCheckboxChangeType) { + if ( + listDest.length > 0 && + isUpdatingFromMainCheckbox && + mainCheckboxChangeType + ) { syncModalWithMainCheckbox(); } }, [isUpdatingFromMainCheckbox, mainCheckboxChangeType]); @@ -280,43 +297,59 @@ export default function FormImageDetail() { 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)) + const checkedPoldaCount = listDest.filter( + (item: any) => + item.levelNumber === 2 && + item.name !== "SATKER POLRI" && + checkedLevels.has(Number(item.id)) ).length; - + 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) => checkedLevels.has(Number(sub.id))).length; + return ( + total + + item.subDestination.filter((sub: any) => + checkedLevels.has(Number(sub.id)) + ).length + ); } return total; }, 0); - - 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; - + + 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 hasSelectedPolres = checkedPolresCount > 0; const hasSelectedSatker = checkedSatkerCount > 0; - + // Update unitSelection berdasarkan yang dipilih di modal - setUnitSelection(prev => { + setUnitSelection((prev) => { const newState = { ...prev }; - + // Update individual checkboxes newState.polda = hasSelectedPolda; newState.polres = hasSelectedPolres; newState.satker = hasSelectedSatker; - + // Update checkbox "semua" berdasarkan semua checkbox yang aktif - newState.semua = newState.nasional && newState.wilayah && newState.international && hasSelectedPolda && hasSelectedPolres && hasSelectedSatker; - + newState.semua = + newState.nasional && + newState.wilayah && + newState.international && + hasSelectedPolda && + hasSelectedPolres && + hasSelectedSatker; + return newState; }); } @@ -326,7 +359,7 @@ export default function FormImageDetail() { const syncModalWithMainCheckbox = () => { if (isUpdatingFromMainCheckbox) { const newCheckedLevels = new Set(checkedLevels); - + // Handle checklist actions - menambahkan semua item ke modal if (mainCheckboxChangeType === "polda_checked") { // Checklist semua polda @@ -335,47 +368,53 @@ export default function FormImageDetail() { newCheckedLevels.add(Number(item.id)); } }); - } else if (mainCheckboxChangeType === "polres_checked") { - // Checklist semua polres, tapi hanya yang poldanya sudah di-checklist - // Jangan checklist sub-item SATKER POLRI - listDest.forEach((item: any) => { - if (item.levelNumber === 2 && item.name !== "SATKER POLRI" && newCheckedLevels.has(Number(item.id))) { - if (item.subDestination) { - item.subDestination.forEach((polres: any) => { - newCheckedLevels.add(Number(polres.id)); - }); - } - } - }); - - // Tidak perlu menghapus SATKER ketika POLRES di-checklist - // Biarkan keduanya bisa aktif bersamaan - // SATKER dan POLRES adalah konsep yang berbeda: - // - SATKER: unit-unit seperti ITWASUM, BAINTELKAM, dll. - // - POLRES: unit-unit seperti POLRES METRO JAKARTA PUSAT, dll. - } 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 === "polres_checked") { + // Checklist semua polres, tapi hanya yang poldanya sudah di-checklist + // Jangan checklist sub-item SATKER POLRI + listDest.forEach((item: any) => { + if ( + item.levelNumber === 2 && + item.name !== "SATKER POLRI" && + newCheckedLevels.has(Number(item.id)) + ) { + if (item.subDestination) { + item.subDestination.forEach((polres: any) => { + newCheckedLevels.add(Number(polres.id)); + }); + } + } + }); + + // Tidak perlu menghapus SATKER ketika POLRES di-checklist + // Biarkan keduanya bisa aktif bersamaan + // SATKER dan POLRES adalah konsep yang berbeda: + // - SATKER: unit-unit seperti ITWASUM, BAINTELKAM, dll. + // - POLRES: unit-unit seperti POLRES METRO JAKARTA PUSAT, dll. + } 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)); + }); + } + }); } // Handle unchecklist actions - menghapus item dari modal else if (mainCheckboxChangeType === "polres_unchecked") { @@ -401,7 +440,9 @@ export default function FormImageDetail() { }); } 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"); + const satkerItem: any = listDest.find( + (item: any) => item.name === "SATKER POLRI" + ); if (satkerItem) { newCheckedLevels.delete(Number(satkerItem.id)); if (satkerItem.subDestination) { @@ -414,9 +455,9 @@ export default function FormImageDetail() { // Clear semua newCheckedLevels.clear(); } - + setCheckedLevels(newCheckedLevels); - + // Reset flag setelah sinkronisasi selesai setIsUpdatingFromMainCheckbox(false); setMainCheckboxChangeType(""); @@ -429,7 +470,7 @@ export default function FormImageDetail() { key: keyof typeof unitSelection, value: boolean ) => { - setFileUnitSelections(prev => { + setFileUnitSelections((prev) => { const newSelections = [...prev]; const currentSelection = { ...newSelections[fileIndex] }; @@ -442,18 +483,47 @@ export default function FormImageDetail() { currentSelection.polda = value; currentSelection.polres = 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 { // 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)) - ); - + 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."); + alert( + "Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES." + ); return prev; // Batalkan perubahan } } @@ -504,15 +574,18 @@ export default function FormImageDetail() { // Validasi khusus untuk POLRES if (key === "polres" && value) { // Cek apakah ada POLDA yang sudah dipilih di modal - const hasSelectedPolda = listDest.some((item: any) => - item.levelNumber === 2 && - item.name !== "SATKER POLRI" && - checkedLevels.has(Number(item.id)) + const hasSelectedPolda = listDest.some( + (item: any) => + item.levelNumber === 2 && + item.name !== "SATKER POLRI" && + checkedLevels.has(Number(item.id)) ); - + if (!hasSelectedPolda) { // Jika tidak ada POLDA yang dipilih, tampilkan peringatan dan batalkan - alert("Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES."); + alert( + "Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES." + ); // Reset flag karena perubahan dibatalkan setIsUpdatingFromMainCheckbox(false); setMainCheckboxChangeType(""); @@ -572,23 +645,32 @@ export default function FormImageDetail() { }; // Fungsi untuk mengupdate checklist levels untuk file tertentu - const handleFileCheckboxChangePlacement = (fileIndex: number, levelId: number) => { + 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") { + 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) => { @@ -597,9 +679,11 @@ export default function FormImageDetail() { } } 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; + 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) => { @@ -607,13 +691,13 @@ export default function FormImageDetail() { }); } } - + newArray[fileIndex] = currentFileLevels; - + // Update checkbox utama berdasarkan perubahan di modal // Pindahkan ke sini agar state sudah ter-update setTimeout(() => updateMainCheckboxFromModal(fileIndex), 0); - + return newArray; }); }; @@ -623,12 +707,12 @@ export default function FormImageDetail() { 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) => + 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) => { @@ -645,12 +729,12 @@ export default function FormImageDetail() { currentFileLevels.add(Number(sub.id)); }); } - + newArray[fileIndex] = currentFileLevels; - + // Update checkbox utama berdasarkan perubahan di modal setTimeout(() => updateMainCheckboxFromModal(fileIndex), 0); - + return newArray; }); }; @@ -658,56 +742,84 @@ export default function FormImageDetail() { // 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))) { + 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; - }); + }, + 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); + + // Update checkbox "semua" berdasarkan semua checkbox yang aktif + currentSelection.semua = + currentSelection.nasional && + currentSelection.wilayah && + currentSelection.international && + currentSelection.polda && + currentSelection.polres && + currentSelection.satker; + + newSelections[fileIndex] = currentSelection; + return newSelections; + }); }; // Fungsi lama untuk kompatibilitas (akan dihapus nanti) @@ -715,18 +827,24 @@ export default function FormImageDetail() { setCheckedLevels((prev: Set) => { const updatedLevels = new Set(prev); const isCurrentlyChecked = updatedLevels.has(levelId); - + if (isCurrentlyChecked) { updatedLevels.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") { + 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) => { updatedLevels.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) => { @@ -735,9 +853,11 @@ export default function FormImageDetail() { } } else { updatedLevels.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; + 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) => { @@ -786,7 +906,7 @@ export default function FormImageDetail() { const temp = []; const unitSelections = []; const checkedLevelsArray = []; - + for (let i = 0; i < length; i++) { temp.push([]); // Inisialisasi state untuk setiap file @@ -802,7 +922,7 @@ export default function FormImageDetail() { // Inisialisasi checkedLevels untuk setiap file checkedLevelsArray.push(new Set()); } - + setFilePlacements(temp); setFileUnitSelections(unitSelections); setFileCheckedLevels(checkedLevelsArray); @@ -892,12 +1012,22 @@ export default function FormImageDetail() { }; const getPlacement = () => { - // console.log("getPlaa", filePlacements); const temp = []; for (let i = 0; i < filePlacements?.length; i++) { if (filePlacements[i]?.length !== 0) { - const now = filePlacements[i]?.filter((a) => a !== "all"); - const data = { mediaFileId: files[i]?.id, placements: now?.join(",") }; + const now = filePlacements[i] + let nowArr = now?.join(",")?.replaceAll("wilayah", "polda"); + nowArr = nowArr?.replaceAll("nasional", "mabes"); + 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); } } @@ -918,12 +1048,12 @@ export default function FormImageDetail() { statusId: status, message: description, files: isUserMabesApprover ? getPlacement() : [], - customLocationPlacement: Array.from(allCheckedLevels).join(","), }; + + console.log("Data Approval : ", data); setModalOpen(false); loading(); const response = await submitApproval(data); - if (response?.error) { error(response.message); return false; @@ -933,8 +1063,6 @@ export default function FormImageDetail() { listFiles: rejectedFiles, }; - // console.log("reject", dataReject); - const resReject = await rejectFiles(dataReject); if (resReject?.error) { @@ -957,6 +1085,43 @@ export default function FormImageDetail() { if (checked) { if (placement === "all") { temp[index] = ["all", "mabes", "polda", "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.polres = true; + currentSelection.satker = true; + currentSelection.semua = true; + + newSelections[index] = currentSelection; + return newSelections; + }); } else if (placement === "satker") { // Ketika satker di-checklist, HANYA tambahkan satker saja // JANGAN otomatis checklist polres @@ -972,7 +1137,9 @@ export default function FormImageDetail() { } // 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"); + const nonSatkerItems = now.filter( + (item) => item !== "satker" && item !== "all" + ); if (nonSatkerItems.length === 3 && !now.includes("all")) { now.push("all"); } @@ -981,13 +1148,45 @@ export default function FormImageDetail() { } 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.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; // Hapus "all" jika tidak semua item ter-checklist if (now.includes("all")) { - const nonSatkerItems = now.filter(item => item !== "satker" && item !== "all"); + const nonSatkerItems = now.filter( + (item) => item !== "satker" && item !== "all" + ); if (nonSatkerItems.length < 3) { const newData = now.filter((b) => b !== "all"); temp[index] = newData; @@ -996,19 +1195,23 @@ 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) => { + 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) @@ -1033,7 +1236,9 @@ export default function FormImageDetail() { }); } else if (placement === "satker") { // Checklist SATKER POLRI dan semua sub-item di bawahnya - const satkerItem: any = listDest.find((item: any) => item.name === "SATKER POLRI"); + const satkerItem: any = listDest.find( + (item: any) => item.name === "SATKER POLRI" + ); if (satkerItem) { currentFileLevels.add(Number(satkerItem.id)); if (satkerItem.subDestination) { @@ -1067,7 +1272,9 @@ export default function FormImageDetail() { }); } else if (placement === "satker") { // Unchecklist SATKER POLRI dan semua sub-item di bawahnya - const satkerItem: any = listDest.find((item: any) => item.name === "SATKER POLRI"); + const satkerItem: any = listDest.find( + (item: any) => item.name === "SATKER POLRI" + ); if (satkerItem) { currentFileLevels.delete(Number(satkerItem.id)); if (satkerItem.subDestination) { @@ -1078,7 +1285,7 @@ export default function FormImageDetail() { } } } - + newArray[fileIndex] = currentFileLevels; return newArray; }); @@ -1440,231 +1647,386 @@ export default function FormImageDetail() { - {t("leave-comment", { defaultValue: "Kelola Persetujuan Konten" })} + {t("leave-comment", { + defaultValue: "Kelola Persetujuan Konten", + })} - -
- {status == "2" && files?.map((file, index) => ( -
- {/* Header File */} -
-
-
- {`files-${index handleImageLoad(e, index)} - className={`h-[80px] object-cover ${ - portraitMap[index] ? "w-auto" : "!w-[120px]" - }`} - /> -
-
-

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)); - }} - /> - -
- ))} +
+ {status == "2" && + files?.map((file, index) => ( +
+ {/* Header File */} +
+
+
+ {`files-${index handleImageLoad(e, index)} + className={`h-[80px] object-cover ${ + portraitMap[index] ? "w-auto" : "!w-[120px]" + }`} + /> +
+
+

+ File {index + 1} +

+

+ {file.fileName} +

+ {isUserMabesApprover ? ( + "" + ) : ( +

+ Selesai +

+ )}
+ +
- {/* Detail Wilayah */} - {fileUnitSelections[index]?.wilayah && ( -
-

Detail Wilayah:

- - {/* Checkbox Sub-kategori dengan tombol Kustom sejajar */} -
- {[ - { key: "polda", label: "POLDA" }, - { key: "polres", label: "POLRES" }, - { 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 POLRES - - -
- {listDest.map((polda: any) => ( -
- {/* Header POLDA */} -
- - {polda.subDestination && ( - - )} -
+ {/* Section Pengaturan Distribusi */} + {isUserMabesApprover ? ( +
+
+ + Pengaturan Distribusi +
- {/* 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) => ( - - ))} -
-
- )} -
- ))} -
-
- - - - - - -
- -
+ {/* 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) + ); + }} + /> + +
+ ))}
+ + {/* Detail Wilayah */} + {fileUnitSelections[index]?.wilayah && ( +
+

+ Detail Wilayah: +

+ + {/* Checkbox Sub-kategori dengan tombol Kustom sejajar */} +
+ {[ + { key: "polda", label: "POLDA" }, + { key: "polres", label: "POLRES" }, + { 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 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) => ( + + ) + )} +
+
+ )} +
+ ))} +
+
+ + + + + + +
+
+
+
+
+
+ )}
- )} -
+
+ ) : ( + "" + )}
-
- ))} + ))}
- + {/* Section Komentar */}
-