diff --git a/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx b/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx index 4cf08040..2f17de4e 100644 --- a/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx +++ b/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx @@ -115,6 +115,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => { const [selectedCategory, setSelectedCategory] = useState([]); const [selectedEventDate, setSelectedEventDate] = useState(null); const roleId = Number(getCookiesDecrypt("urie")) || 0; + const levelNumber = Number(getCookiesDecrypt("ulne")) || 0; const userLevelId = Number(getCookiesDecrypt("ulie")) || 0; const [calendarEvents, setCalendarEvents] = useState([]); const [isLoading, setIsLoading] = useState(false); @@ -414,7 +415,9 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
{events.length === 0 ? (
-

{t("no-data-yet", { defaultValue: "No Data Yet" })}

+

+ {t("no-data-yet", { defaultValue: "No Data Yet" })} +

) : ( <> @@ -526,7 +529,16 @@ const CalendarView = ({ categories }: CalendarViewProps) => { - {[3, 11, 2, 12].includes(roleId) && ( + {/* {[3, 11, 2, 12].includes(roleId) && ( + + )} */} + {[3, 11, 2, 12].includes(roleId) && levelNumber !== 3 && ( - {t("monitoring-results", { defaultValue: "Monitoring Results" })} + + {t("monitoring-results", { + defaultValue: "Monitoring Results", + })} + {getModalContent()} diff --git a/app/[locale]/(protected)/contributor/agenda-setting/event-modal.tsx b/app/[locale]/(protected)/contributor/agenda-setting/event-modal.tsx index 20164984..e4238262 100644 --- a/app/[locale]/(protected)/contributor/agenda-setting/event-modal.tsx +++ b/app/[locale]/(protected)/contributor/agenda-setting/event-modal.tsx @@ -108,8 +108,8 @@ const EventModal = ({ const router = useRouter(); const pathname = usePathname(); const [isLoading, setIsLoading] = useState(false); - const [checkedLevels, setCheckedLevels] = useState(new Set()); - const [expandedPolda, setExpandedPolda] = useState([{}]); + const [checkedLevels, setCheckedLevels] = useState>(new Set()); + const [expandedPolda, setExpandedPolda] = useState>({}); const [audioFile, setAudioFile] = useState(null); const [isRecording, setIsRecording] = useState(false); const [timer, setTimer] = useState(120); @@ -151,7 +151,13 @@ const EventModal = ({ satker: false, international: false, }); - const levelNumber = getCookiesDecrypt("ulne"); + + // State untuk melacak apakah perubahan berasal dari checkbox Jenis Agenda + const [isUpdatingFromJenisAgenda, setIsUpdatingFromJenisAgenda] = useState(false); + // State untuk melacak jenis perubahan spesifik + const [jenisAgendaChangeType, setJenisAgendaChangeType] = useState(""); + + const levelNumber = Number(getCookiesDecrypt("ulne")) || 0; const userLevelId = getCookiesDecrypt("ulie"); const poldaState = Cookies.get("state"); const [agendaType, setAgendaType] = React.useState(""); @@ -253,15 +259,242 @@ const EventModal = ({ fetchDetailData(); }, [event, setValue]); + // useEffect untuk sinkronisasi checkbox modal dengan Jenis Agenda + useEffect(() => { + if (listDest.length > 0 && isUpdatingFromJenisAgenda && jenisAgendaChangeType) { + syncModalWithJenisAgenda(); + } + }, [isUpdatingFromJenisAgenda, jenisAgendaChangeType]); + + // useEffect untuk update wilayahPublish ketika pilihan modal berubah + useEffect(() => { + if (!isUpdatingFromJenisAgenda && listDest.length > 0) { + updateWilayahPublishFromModal(); + } + }, [checkedLevels, isUpdatingFromJenisAgenda]); + + // Fungsi untuk update wilayahPublish berdasarkan checkbox modal + const updateWilayahPublishFromModal = () => { + // Hanya update jika tidak sedang dalam proses update dari Jenis Agenda + if (!isUpdatingFromJenisAgenda && 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 checkedPolresCount = listDest.reduce((total: number, item: any) => { + if (item.subDestination) { + 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; + + // Checkbox aktif jika ADA item yang dipilih dalam kategori tersebut + const hasSelectedPolda = checkedPoldaCount > 0; + const hasSelectedPolres = checkedPolresCount > 0; + const hasSelectedSatker = checkedSatkerCount > 0; + + // Update arrays untuk backend + const newSelectedPolda = listDest + .filter((item: any) => + item.levelNumber === 2 && + item.name !== "SATKER POLRI" && + checkedLevels.has(Number(item.id)) + ) + .map((item: any) => String(item.id)); + + const newSelectedPolres: string[] = []; + listDest.forEach((item: any) => { + if (item.subDestination) { + item.subDestination.forEach((sub: any) => { + if (checkedLevels.has(Number(sub.id))) { + newSelectedPolres.push(String(sub.id)); + } + }); + } + }); + + const newSelectedSatker: string[] = []; + if (satkerItem) { + if (checkedLevels.has(Number(satkerItem.id))) { + newSelectedSatker.push(String(satkerItem.id)); + } + if (satkerItem.subDestination) { + satkerItem.subDestination.forEach((sub: any) => { + if (checkedLevels.has(Number(sub.id))) { + newSelectedSatker.push(String(sub.id)); + } + }); + } + } + + // Update state arrays + setSelectedPolda(newSelectedPolda); + setSelectedPolres(newSelectedPolres); + setSelectedSatker(newSelectedSatker); + + // Update wilayahPublish berdasarkan yang dipilih di modal + setWilayahPublish(prev => { + const newState = { ...prev }; + + // Update individual checkboxes + newState.polda = hasSelectedPolda; + newState.polres = hasSelectedPolres; + newState.satker = hasSelectedSatker; + + // Update checkbox "semua" berdasarkan level user + if (levelNumber === 1) { + // Level 1: semua checkbox harus aktif (nasional, polda, polres, satker, international) + newState.semua = newState.nasional && hasSelectedPolda && hasSelectedPolres && hasSelectedSatker && newState.international; + } else if (levelNumber === 2) { + // Level 2: hanya polres yang perlu aktif + newState.semua = hasSelectedPolres; + } else { + newState.semua = false; + } + + return newState; + }); + + // Update agendaType berdasarkan checkbox yang aktif + const selectedKeys = []; + if (hasSelectedPolda) selectedKeys.push(wilayahValueMap.polda); + if (hasSelectedPolres) selectedKeys.push(wilayahValueMap.polres); + if (hasSelectedSatker) selectedKeys.push(wilayahValueMap.satker); + + setAgendaType(selectedKeys.join(",")); + } + }; + + // Fungsi untuk sinkronisasi checkbox modal dengan Jenis Agenda + const syncModalWithJenisAgenda = () => { + // Hanya jalankan sinkronisasi jika perubahan berasal dari checkbox Jenis Agenda + if (isUpdatingFromJenisAgenda) { + const newCheckedLevels = new Set(checkedLevels); + + // Handle checklist actions - menambahkan semua item ke modal + if (jenisAgendaChangeType === "polda_checked") { + // Checklist semua polda + listDest.forEach((item: any) => { + if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { + newCheckedLevels.add(Number(item.id)); + } + }); + } else if (jenisAgendaChangeType === "polres_checked") { + // Checklist semua polres, tapi hanya yang poldanya sudah di-checklist + 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)); + }); + } + } + }); + } else if (jenisAgendaChangeType === "satker_checked") { + // Checklist satker + const satkerItem: any = listDest.find((item: any) => item.name === "SATKER POLRI"); + if (satkerItem) { + newCheckedLevels.add(Number(satkerItem.id)); + if (satkerItem.subDestination) { + satkerItem.subDestination.forEach((sub: any) => { + newCheckedLevels.add(Number(sub.id)); + }); + } + } + } + // Handle unchecklist actions - menghapus item dari modal + else if (jenisAgendaChangeType === "polres_unchecked") { + // Clear polres dari checkedLevels + listDest.forEach((item: any) => { + if (item.subDestination) { + item.subDestination.forEach((polres: any) => { + newCheckedLevels.delete(Number(polres.id)); + }); + } + }); + } else if (jenisAgendaChangeType === "polda_unchecked") { + // Clear polda dan polres dari checkedLevels + listDest.forEach((item: any) => { + if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { + newCheckedLevels.delete(Number(item.id)); + // Juga clear polres dari polda ini + if (item.subDestination) { + item.subDestination.forEach((polres: any) => { + newCheckedLevels.delete(Number(polres.id)); + }); + } + } + }); + setWilayahPublish(prev => ({ ...prev, polres: false })); + } else if (jenisAgendaChangeType === "satker_unchecked") { + // Clear satker 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)); + }); + } + } + } + + setCheckedLevels(newCheckedLevels); + + // Reset flag setelah sinkronisasi selesai + setIsUpdatingFromJenisAgenda(false); + setJenisAgendaChangeType(""); + } + }; + useEffect(() => { setIsDatePickerOpen(false); }, [onClose]); + useEffect(() => { + async function fetchPoldaPolres() { + 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); + } catch (error) { + console.error("Error fetching Polda/Polres data:", error); + } + } + fetchPoldaPolres(); + }, []); + const handleCheckboxChange = (levelId: number) => { setCheckedLevels((prev) => { const updatedLevels = new Set(prev); - if (updatedLevels.has(levelId)) { + 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.subDestination.forEach((polres: any) => { + updatedLevels.delete(Number(polres.id)); + }); + } } else { updatedLevels.add(levelId); } @@ -279,6 +512,10 @@ const EventModal = ({ }; const toggleWilayah = (key: string) => { + // Set flag bahwa perubahan berasal dari checkbox Jenis Agenda + setIsUpdatingFromJenisAgenda(true); + setJenisAgendaChangeType(key + (wilayahPublish[key as keyof typeof wilayahPublish] ? "_unchecked" : "_checked")); + setWilayahPublish((prev: any) => { let newState = { ...prev }; if (key === "semua") { @@ -294,15 +531,96 @@ const EventModal = ({ if (newChecked) { setAgendaType("0,1,2,3,4,5"); + // Checklist semua item di modal ketika "semua" di-checklist + const allCheckedLevels = new Set(); + listDest.forEach((item: any) => { + allCheckedLevels.add(Number(item.id)); + if (item.subDestination) { + item.subDestination.forEach((sub: any) => { + allCheckedLevels.add(Number(sub.id)); + }); + } + }); + setCheckedLevels(allCheckedLevels); } else { setAgendaType(""); + // Clear semua pilihan modal ketika "semua" di-unchecklist + setCheckedLevels(new Set()); } return newState; } + // Validasi khusus untuk POLRES + if (key === "polres" && !prev[key]) { + // 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)) + ); + + if (!hasSelectedPolda) { + // Jika tidak ada POLDA yang dipilih, tampilkan peringatan dan batalkan + alert("Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES."); + // Reset flag karena perubahan dibatalkan + setIsUpdatingFromJenisAgenda(false); + setJenisAgendaChangeType(""); + return prev; // Batalkan perubahan + } + } + newState[key] = !prev[key]; - newState.semua = false; + + // Jika checkbox di-unchecklist, clear pilihan modal yang sesuai + if (prev[key]) { + const newCheckedLevels = new Set(checkedLevels); + if (key === "polda") { + // Clear polda dan polres + listDest.forEach((item: any) => { + if (item.levelNumber === 2 && item.name !== "SATKER POLRI") { + newCheckedLevels.delete(Number(item.id)); + if (item.subDestination) { + item.subDestination.forEach((polres: any) => { + newCheckedLevels.delete(Number(polres.id)); + }); + } + } + }); + } else if (key === "polres") { + // Clear polres + listDest.forEach((item: any) => { + if (item.subDestination) { + item.subDestination.forEach((polres: any) => { + newCheckedLevels.delete(Number(polres.id)); + }); + } + }); + } else if (key === "satker") { + // Clear satker + 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)); + }); + } + } + } + setCheckedLevels(newCheckedLevels); + } + + // Update checkbox "semua" berdasarkan status semua checkbox lainnya + // Untuk level 1: semua, nasional, polda, polres, satker, international harus aktif + // Untuk level 2: semua, polres harus aktif + if (levelNumber === 1) { + newState.semua = newState.nasional && newState.polda && newState.polres && newState.satker && newState.international; + } else if (levelNumber === 2) { + newState.semua = newState.polres; + } else { + newState.semua = false; + } const selectedKeys = Object.entries(newState) .filter(([k, v]) => v && k !== "semua") @@ -449,7 +767,7 @@ const EventModal = ({ const onDeleteEventAction = async () => { try { - } catch (error) {} + } catch (error) { } }; const handleOpenDeleteModal = (eventId: string) => { @@ -629,7 +947,7 @@ const EventModal = ({ ); }; - const handleRemoveFile = (id: number) => {}; + const handleRemoveFile = (id: number) => { }; async function doDelete(id: any) { loading(); @@ -797,7 +1115,8 @@ const EventModal = ({
- {roleId === 1 && ( + {levelNumber === 1 && ( + <>
- )} -
Polda - {wilayahPublish.polda && ( - - setSelectedPolda(data) - } - /> - )}
- {(roleId === 1 || roleId === 4 || roleId === 3) && ( + + )} + + {(levelNumber === 1 || levelNumber === 2) && (
Polres - {wilayahPublish.polres && ( - - setSelectedPolres(data) - } - /> - )}
)} - {(roleId === 1 || roleId === 2) && ( + + {levelNumber === 1 && ( + <>
Satker - {wilayahPublish.satker && ( - - setSelectedSatker(data) - } - /> - )}
- )} - {roleId === 1 && (
+ )} + +
+ + + + + + + + Daftar Wilayah Polda dan Polres + + +
+ {listDest?.map((polda: any) => ( +
+ + {expandedPolda[polda.id] && ( +
+ + {polda?.subDestination?.map((polres: any) => ( + + ))} +
+ )} +
+ ))} +
+
+
+
@@ -1099,8 +1479,7 @@ const EventModal = ({ type="button" onClick={onPlayPause} disabled={isPlaying} - className={`flex items-center gap-2 ${ - isPlaying + className={`flex items-center gap-2 ${isPlaying ? "bg-gray-300 cursor-not-allowed" : "bg-primary text-white" } p-2 rounded`} diff --git a/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx b/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx index 1c0a57d2..eea434ee 100644 --- a/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx +++ b/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx @@ -67,7 +67,6 @@ import useTableColumns from "./columns"; const TableTeks = () => { const router = useRouter(); const searchParams = useSearchParams(); - const [dataTable, setDataTable] = React.useState([]); const [totalData, setTotalData] = React.useState(1); const [sorting, setSorting] = React.useState([]); @@ -77,7 +76,7 @@ const TableTeks = () => { const [columnVisibility, setColumnVisibility] = React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); - const [showData, setShowData] = React.useState("50"); + const [showData, setShowData] = React.useState("10"); const [pagination, setPagination] = React.useState({ pageIndex: 0, pageSize: Number(showData), @@ -88,7 +87,6 @@ const TableTeks = () => { const [search, setSearch] = React.useState(""); const userId = getCookiesDecrypt("uie"); const userLevelId = getCookiesDecrypt("ulie"); - const [categories, setCategories] = React.useState([]); const [selectedCategories, setSelectedCategories] = React.useState( [] diff --git a/app/[locale]/(protected)/contributor/report/components/report-table.tsx b/app/[locale]/(protected)/contributor/report/components/report-table.tsx index 4280038e..9a1f01ad 100644 --- a/app/[locale]/(protected)/contributor/report/components/report-table.tsx +++ b/app/[locale]/(protected)/contributor/report/components/report-table.tsx @@ -88,7 +88,7 @@ const ReportTable = () => { const [columnVisibility, setColumnVisibility] = React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); - const [showData, setShowData] = React.useState("50"); + const [showData, setShowData] = React.useState("10"); const [pagination, setPagination] = React.useState({ pageIndex: 0, pageSize: Number(showData), @@ -106,6 +106,8 @@ const ReportTable = () => { const [statusFilter, setStatusFilter] = React.useState([]); const [openPreview, setOpenPreview] = React.useState(false); const [previewData, setPreviewData] = React.useState(null); + const [openDateDialog, setOpenDateDialog] = React.useState(false); + const [reportDate, setReportDate] = React.useState(""); const handlePreview = (id: string) => { const url = `https://mediahub.polri.go.id/api/v2/media/report/view?id=${id}`; @@ -181,8 +183,6 @@ const ReportTable = () => { ? prev.filter((id: any) => id !== categoryId) : [...prev, categoryId] ); - - // Perbarui filter kategori setCategoryFilter((prev) => { const updatedCategories = prev.split(",").filter(Boolean).map(Number); @@ -203,22 +203,65 @@ const ReportTable = () => { } const handleSearch = (e: React.ChangeEvent) => { - setSearch(e.target.value); // Perbarui state search - table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + setSearch(e.target.value); + table.getColumn("judul")?.setFilterValue(e.target.value); }; - const handleGenerateReport = async () => { - const today = new Date(); - const formattedDate = format(today, "dd-MM-yyyy"); // Hasil: 22-04-2025 - const title = `Report ${formattedDate}`; + // const handleGenerateReport = async () => { + // const today = new Date(); + // const formattedDate = format(today, "dd-MM-yyyy"); + // const title = `Report ${formattedDate}`; + // const requestData = { + // title, + // date: reportDate, + // }; + + // try { + // const response = await saveReport(requestData); + + // if (response?.error) { + // MySwal.fire( + // "Error", + // response?.message || "Gagal menyimpan laporan", + // "error" + // ); + // return; + // } + + // MySwal.fire({ + // title: "Sukses", + // text: "Laporan berhasil dibuat.", + // icon: "success", + // confirmButtonColor: "#3085d6", + // confirmButtonText: "OK", + // }).then(() => { + // fetchData(); + // }); + // } catch (error) { + // console.error("Generate report error:", error); + // MySwal.fire("Error", "Terjadi kesalahan saat membuat laporan", "error"); + // } + // }; + + const handleGenerateReport = async () => { + if (!reportDate) { + MySwal.fire( + "Warning", + "Silakan pilih tanggal laporan terlebih dahulu", + "warning" + ); + return; + } + + const title = `Report ${format(new Date(reportDate), "dd-MM-yyyy")}`; const requestData = { title, + date: reportDate, }; try { const response = await saveReport(requestData); - if (response?.error) { MySwal.fire( "Error", @@ -235,7 +278,8 @@ const ReportTable = () => { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - fetchData(); // Refresh tabel setelah generate + fetchData(); + setReportDate(""); }); } catch (error) { console.error("Generate report error:", error); @@ -266,10 +310,19 @@ const ReportTable = () => {
- {t("table", { defaultValue: "Table" })} {t("report", { defaultValue: "Report" })} + {t("table", { defaultValue: "Table" })}{" "} + {t("report", { defaultValue: "Report" })}
- */} + @@ -469,6 +522,38 @@ const ReportTable = () => { totalPage={totalPage} />
+ + + + Pilih Tanggal Laporan + +
+ + setReportDate(e.target.value)} + /> +
+ + +
+
+
+
); }; 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 85ac17b6..c0672f25 100644 --- a/app/[locale]/(protected)/contributor/schedule/calendar-polri/component/columns.tsx +++ b/app/[locale]/(protected)/contributor/schedule/calendar-polri/component/columns.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { ColumnDef } from "@tanstack/react-table"; import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react"; -import { cn } from "@/lib/utils"; +import { cn, getCookiesDecrypt } from "@/lib/utils"; import { DropdownMenu, DropdownMenuContent, @@ -17,9 +17,10 @@ import withReactContent from "sweetalert2-react-content"; import Swal from "sweetalert2"; import { error } from "@/lib/swal"; import { deleteCalendar } from "@/service/schedule/schedule"; +import { loading, success } from "@/config/swal"; const useTableColumns = () => { - const t = useTranslations("Table"); // Panggil di dalam hook + const t = useTranslations("Table"); const columns: ColumnDef[] = [ { @@ -100,15 +101,13 @@ 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 async function doDelete(id: any) { - // loading(); - const data = { - id, - }; - const response = await deleteCalendar(id); - if (response?.error) { error(response.message); return false; @@ -144,6 +143,29 @@ 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 ( @@ -156,34 +178,134 @@ const useTableColumns = () => { - - - - Detail + {canView && ( + + + + Detail + + + )} + + {canEdit && ( + + + + Edit + + + )} + + {canDelete && ( + handleDeleteCalendars(row.original.id)} + className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none" + > + + Delete - - - - - Edit - - - handleDeleteCalendars(row.original.id)} - className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none" - > - - Delete - + )} ); }, }, + + // { + // id: "actions", + // accessorKey: "action", + // header: t("action", { defaultValue: "Action" }), + // enableHiding: false, + // cell: ({ row }) => { + // const MySwal = withReactContent(Swal); + + // async function doDelete(id: any) { + // // loading(); + // const data = { + // id, + // }; + + // const response = await deleteCalendar(id); + + // if (response?.error) { + // error(response.message); + // return false; + // } + // success(); + // } + + // function success() { + // MySwal.fire({ + // title: "Sukses", + // icon: "success", + // confirmButtonColor: "#3085d6", + // confirmButtonText: "OK", + // }).then((result) => { + // if (result.isConfirmed) { + // window.location.reload(); + // } + // }); + // } + + // const handleDeleteCalendars = (id: any) => { + // MySwal.fire({ + // title: "Hapus Data", + // text: "", + // icon: "warning", + // showCancelButton: true, + // cancelButtonColor: "#3085d6", + // confirmButtonColor: "#d33", + // confirmButtonText: "Hapus", + // }).then((result) => { + // if (result.isConfirmed) { + // doDelete(id); + // } + // }); + // }; + // return ( + // + // + // + // + // + // + // + // + // Detail + // + // + // + // + // + // Edit + // + // + // handleDeleteCalendars(row.original.id)} + // className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none" + // > + // + // Delete + // + // + // + // ); + // }, + // }, ]; return columns; diff --git a/components/form/communication/escalation-forward-form.tsx b/components/form/communication/escalation-forward-form.tsx index 7ac0e030..743b6f5c 100644 --- a/components/form/communication/escalation-forward-form.tsx +++ b/components/form/communication/escalation-forward-form.tsx @@ -54,8 +54,15 @@ interface Option { userLevelId: string; } +// const taskSchema = z.object({ +// title: z.string().optional(), +// description: z.string().min(2, { +// message: "Narasi Penugasan harus lebih dari 2 karakter.", +// }), +// }); + const taskSchema = z.object({ - title: z.string().min(1, { message: "Judul diperlukan" }), + title: z.string().optional(), description: z.string().min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter.", }), @@ -89,13 +96,11 @@ type OptionType = { export default function FormQuestionsForward() { const MySwal = withReactContent(Swal); const { id } = useParams() as { id: string }; - const [detail, setDetail] = useState(); const [ticketReply, setTicketReply] = useState([]); const [replyVisible, setReplyVisible] = useState(false); const [listDiscussion, setListDiscussion] = useState(); const [message, setMessage] = useState(""); - const [detailTickets, setDetailTickets] = useState(null); // const [selectedPriority, setSelectedPriority] = useState(""); const [selectedPriority, setSelectedPriority] = useState( @@ -202,6 +207,8 @@ export default function FormQuestionsForward() { title: "Sukses", text: "Data berhasil diperbarui.", icon: "success", + }).then(() => { + window.location.href = "/in/supervisor/communications/questions/all"; }); getTicketReply(); @@ -262,7 +269,7 @@ export default function FormQuestionsForward() { const newReply = { id: replies.length + 1, - name: "Mabes Polri - Approver", // Sesuaikan dengan data dinamis jika ada + name: "Mabes Polri - Approver", message: replyMessage, timestamp: new Date().toISOString().slice(0, 19).replace("T", " "), }; diff --git a/components/form/content/audio-detail-form.tsx b/components/form/content/audio-detail-form.tsx index 39e81caa..2af8b217 100644 --- a/components/form/content/audio-detail-form.tsx +++ b/components/form/content/audio-detail-form.tsx @@ -19,7 +19,6 @@ import { } from "@/components/ui/select"; import { Checkbox } from "@/components/ui/checkbox"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; - import { register } from "module"; import { Switch } from "@/components/ui/switch"; import Cookies from "js-cookie"; @@ -35,7 +34,7 @@ import { getDataApprovalByMediaUpload, } from "@/service/curated-content/curated-content"; import { Badge } from "@/components/ui/badge"; -import { MailIcon, Music } from "lucide-react"; +import { ChevronDown, ChevronUp, MailIcon, Music } from "lucide-react"; import { Swiper, SwiperSlide } from "swiper/react"; import "swiper/css"; import "swiper/css/free-mode"; @@ -51,6 +50,8 @@ import { Dialog, DialogContent, DialogTitle, + DialogTrigger, + DialogClose, } from "@/components/ui/dialog"; import { Textarea } from "@/components/ui/textarea"; import { loading } from "@/config/swal"; @@ -66,6 +67,7 @@ import { formatDateToIndonesian } from "@/utils/globals"; import ApprovalHistoryModal from "@/components/modal/approval-history-modal"; import { useDropzone } from "react-dropzone"; import AudioPlayer from "@/components/audio-player"; +import { getUserLevelForAssignments } from "@/service/task"; const imageSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -115,6 +117,17 @@ const ViewEditor = dynamic( { ssr: false } ); +interface Destination { + id: string; + name: string; + subDestination?: SubDestination[]; +} + +interface SubDestination { + id: string; + name: string; +} + export default function FormAudioDetail() { const MySwal = withReactContent(Swal); const router = useRouter(); @@ -157,6 +170,212 @@ export default function FormAudioDetail() { const [wavesurfer, setWavesurfer] = useState(); const [isPlaying, setIsPlaying] = useState(false); const [approval, setApproval] = useState(); + const [expandedPolda, setExpandedPolda] = useState([{}]); + const [unitSelection, setUnitSelection] = useState({ + semua: false, + nasional: false, + wilayah: false, + international: false, + polda: false, + polres: false, + satker: false, + }); + 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) => ({ + ...prev, + [id]: !prev[id], + })); + }; + + useEffect(() => { + if (detail?.assignedToTopLevel) { + const outputSet = new Set( + detail.assignedToTopLevel.split(",").map(Number) + ); + setUnitSelection({ + semua: outputSet.has(0), + nasional: outputSet.has(1), + wilayah: outputSet.has(2), + international: outputSet.has(3), + polda: outputSet.has(4), + polres: outputSet.has(5), + satker: outputSet.has(6), + }); + } + }, [detail?.fileTypeOutput]); + + 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(() => { + const updated = new Set(checkedLevels); + + if (unitSelection.polda) { + listDest.forEach((polda) => { + updated.add(polda.id); + }); + } + + if (unitSelection.polres) { + listDest.forEach((polda) => { + polda?.subDestination?.forEach((polres: any) => { + updated.add(polres.id); + }); + }); + } + + setCheckedLevels(updated); + }, [unitSelection.polda, unitSelection.polres, listDest]); + + const handleUnitChange = ( + key: keyof typeof unitSelection, + value: boolean + ) => { + if (key === "semua") { + const newState = { + semua: value, + nasional: value, + wilayah: value, + international: value, + polda: value, + polres: value, + satker: value, + }; + setUnitSelection(newState); + } else { + const updatedSelection = { + ...unitSelection, + [key]: value, + }; + + const allChecked = [ + "nasional", + "wilayah", + "international", + "polda", + "polres", + "satker", + ].every((k) => updatedSelection[k as keyof typeof unitSelection]); + + updatedSelection.semua = allChecked; + + setUnitSelection(updatedSelection); + } + }; + + const handleCheckboxChangePlacement = (levelId: number) => { + setCheckedLevels((prev: any) => { + const updatedLevels = new Set(prev); + if (updatedLevels.has(levelId)) { + updatedLevels.delete(levelId); + } else { + updatedLevels.add(levelId); + } + return updatedLevels; + }); + }; const onDrop = (acceptedFiles: File[]) => { setUploadedFiles(acceptedFiles); @@ -249,7 +468,7 @@ export default function FormAudioDetail() { if (findCategory) { // setValue("categoryId", findCategory.id); - setSelectedCategory(findCategory.id); + setSelectedCategory(findCategory.id); const response = await getTagsBySubCategoryId(findCategory.id); setTags(response?.data?.data); } @@ -285,6 +504,13 @@ export default function FormAudioDetail() { }); setupPlacementCheck(details?.files?.length); + if (details?.assignedToLevel) { + const levels = new Set( + details.assignedToLevel.split(",").map(Number) + ); + setCheckedLevels(levels); + } + if (details?.publishedForObject) { const publisherIds = details?.publishedForObject.map( (obj: any) => obj.id @@ -360,9 +586,9 @@ export default function FormAudioDetail() { // 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(",") }; + if (filePlacements[i]?.length !== 0) { + const now = filePlacements[i]?.filter((a) => a !== "all"); + const data = { mediaFileId: files[i]?.id, placements: now.join(",") }; temp.push(data); } } @@ -376,6 +602,7 @@ export default function FormAudioDetail() { message: description, // files: [], files: isUserMabesApprover ? getPlacement() : [], + customLocationPlacement: Array.from(checkedLevels).join(","), }; setModalOpen(false); loading(); @@ -411,6 +638,7 @@ export default function FormAudioDetail() { setRejectedFiles(rejects); } +<<<<<<< HEAD const setupPlacement = ( index: number, placement: string, @@ -443,6 +671,39 @@ export default function FormAudioDetail() { } 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); + // }; +>>>>>>> e5a2fc2bf1efcf9f3a60081a2633b8a3a3dd885c const handleMain = ( type: string, @@ -480,6 +741,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 ? ( @@ -701,214 +1290,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} +

+
- {isUserMabesApprover && ( -
-
- - setupPlacement(index, "all", Boolean(e)) - } - /> - -
-
- - setupPlacement(index, "mabes", Boolean(e)) - } - /> - -
-
- - setupPlacement(index, "polda", Boolean(e)) - } - /> - -
+ +
-
- - setupPlacement( - index, - "international", - Boolean(e) - ) - } - /> - + {/* 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) + ); + }} + /> + +
+ ))}
- )} + + {/* 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) => ( + + ) + )} +
+
+ )} +
+ ))} +
+
+ + + + + + +
+
+
+
+
+
+ )} +
- )) - : ""} -
-