fix: placement content satker

This commit is contained in:
Sabda Yagra 2025-12-15 20:41:18 +07:00
parent 9c997fd85d
commit ae6e22e05f
4 changed files with 1262 additions and 585 deletions

View File

@ -184,6 +184,10 @@ export default function FormAudioDetail() {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [listDest, setListDest] = useState<Destination[]>([]); const [listDest, setListDest] = useState<Destination[]>([]);
const [checkedLevels, setCheckedLevels] = useState<any>(new Set()); const [checkedLevels, setCheckedLevels] = useState<any>(new Set());
const isUploadedBySatkerLevel3 =
Number(detail?.uploadedBy?.userLevel?.levelNumber) === 3;
// State untuk setiap file secara individual - checklist levels // State untuk setiap file secara individual - checklist levels
const [fileCheckedLevels, setFileCheckedLevels] = useState< const [fileCheckedLevels, setFileCheckedLevels] = useState<
Array<Set<number>> Array<Set<number>>
@ -218,42 +222,60 @@ export default function FormAudioDetail() {
const currentSelection = { ...newSelections[fileIndex] }; const currentSelection = { ...newSelections[fileIndex] };
if (key === "semua") { if (key === "semua") {
// Jika klik Semua, set semua value ke true/false
currentSelection.semua = value; currentSelection.semua = value;
currentSelection.nasional = value; currentSelection.nasional = value;
currentSelection.wilayah = value;
currentSelection.international = value; currentSelection.international = value;
currentSelection.polda = value;
currentSelection.polres = value;
currentSelection.satker = value;
// Update fileCheckedLevels untuk sinkronisasi dengan modal if (isUploadedBySatkerLevel3) {
setFileCheckedLevels((prevLevels) => { currentSelection.wilayah = false;
const newArray = [...prevLevels]; currentSelection.polda = false;
const currentFileLevels = new Set<number>( currentSelection.polres = false;
newArray[fileIndex] || new Set() currentSelection.satker = false;
);
if (value) { setFileCheckedLevels((prevLevels) => {
// Checklist semua item di modal const newArray = [...prevLevels];
listDest.forEach((item: any) => { const currentFileLevels = new Set<number>(
currentFileLevels.add(Number(item.id)); newArray[fileIndex] || new Set()
if (item.subDestination) { );
item.subDestination.forEach((sub: any) => {
currentFileLevels.add(Number(sub.id));
});
}
});
} else {
// Unchecklist semua item di modal
currentFileLevels.clear();
}
newArray[fileIndex] = currentFileLevels; if (!value) {
return newArray; currentFileLevels.clear();
}); }
newArray[fileIndex] = currentFileLevels;
return newArray;
});
} else {
// 🔁 LOGIC LAMA (TIDAK DIUBAH)
currentSelection.wilayah = value;
currentSelection.polda = value;
currentSelection.polres = value;
currentSelection.satker = value;
setFileCheckedLevels((prevLevels) => {
const newArray = [...prevLevels];
const currentFileLevels = new Set<number>(
newArray[fileIndex] || new Set()
);
if (value) {
listDest.forEach((item: any) => {
currentFileLevels.add(Number(item.id));
if (item.subDestination) {
item.subDestination.forEach((sub: any) => {
currentFileLevels.add(Number(sub.id));
});
}
});
} else {
currentFileLevels.clear();
}
newArray[fileIndex] = currentFileLevels;
return newArray;
});
}
} else { } else {
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist
if (key === "polres" && value) { if (key === "polres" && value) {
const currentFileCheckedLevels = fileCheckedLevels[fileIndex]; const currentFileCheckedLevels = fileCheckedLevels[fileIndex];
const hasSelectedPolda = const hasSelectedPolda =
@ -269,14 +291,12 @@ export default function FormAudioDetail() {
alert( alert(
"Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES." "Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES."
); );
return prev; // Batalkan perubahan return prev;
} }
} }
// Update salah satu saja
currentSelection[key] = value; currentSelection[key] = value;
// Cek apakah semua selain "semua" sudah dicentang
const allChecked = [ const allChecked = [
"nasional", "nasional",
"wilayah", "wilayah",
@ -294,6 +314,92 @@ export default function FormAudioDetail() {
}); });
}; };
// 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;
// // Update fileCheckedLevels untuk sinkronisasi dengan modal
// setFileCheckedLevels((prevLevels) => {
// const newArray = [...prevLevels];
// const currentFileLevels = new Set<number>(
// 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))
// );
// 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) => { const toggleExpand = (id: number) => {
setExpandedPolda((prev) => ({ setExpandedPolda((prev) => ({
...prev, ...prev,
@ -718,8 +824,15 @@ export default function FormAudioDetail() {
) => { ) => {
let temp = [...filePlacements]; let temp = [...filePlacements];
if (checked) { if (checked) {
// if (placement === "all") {
// temp[index] = ["all", "mabes", "polda", "international"];
if (placement === "all") { if (placement === "all") {
temp[index] = ["all", "mabes", "polda", "international"]; if (isUploadedBySatkerLevel3) {
temp[index] = ["mabes", "international"];
} else {
temp[index] = ["all", "mabes", "polda", "international"];
}
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik // Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik
setFileCheckedLevels((prevLevels) => { setFileCheckedLevels((prevLevels) => {
@ -1477,6 +1590,56 @@ export default function FormAudioDetail() {
key: "international", key: "international",
label: "Internasional", label: "Internasional",
}, },
]
.filter(
(item) =>
!(
isUploadedBySatkerLevel3 &&
item.key === "wilayah"
)
)
.map((item) => (
<div
key={item.key}
className="flex items-center gap-2 p-2 border border-gray-200 rounded-md hover:bg-gray-50"
>
<Checkbox
id={`${item.key}-${index}`}
checked={
fileUnitSelections[index]?.[
item.key as keyof typeof unitSelection
] || false
}
onCheckedChange={(value) => {
handleFileUnitChange(
index,
item.key as keyof typeof unitSelection,
value as boolean
);
setupPlacement(
index,
item.key,
Boolean(value)
);
}}
/>
<Label
htmlFor={`${item.key}-${index}`}
className="text-sm font-medium cursor-pointer"
>
{item.label}
</Label>
</div>
))}
{/* {[
{ key: "semua", label: "Semua" },
{ key: "nasional", label: "Nasional" },
{ key: "wilayah", label: "Wilayah" },
{
key: "international",
label: "Internasional",
},
].map((item, idx) => ( ].map((item, idx) => (
<div <div
key={item.key} key={item.key}
@ -1509,7 +1672,7 @@ export default function FormAudioDetail() {
{item.label} {item.label}
</Label> </Label>
</div> </div>
))} ))} */}
</div> </div>
</div> </div>

View File

@ -474,42 +474,69 @@ export default function FormImageDetail() {
const currentSelection = { ...newSelections[fileIndex] }; const currentSelection = { ...newSelections[fileIndex] };
if (key === "semua") { if (key === "semua") {
// Jika klik Semua, set semua value ke true/false // Jika klik Semua
currentSelection.semua = value; currentSelection.semua = value;
// ✅ Tetap berlaku untuk semua kondisi
currentSelection.nasional = value; currentSelection.nasional = value;
currentSelection.wilayah = value;
currentSelection.international = value; currentSelection.international = value;
currentSelection.polda = value;
currentSelection.polres = value;
currentSelection.satker = value;
// Update fileCheckedLevels untuk sinkronisasi dengan modal if (isUploadedBySatkerLevel3) {
setFileCheckedLevels((prevLevels) => { // 🔹 TAMBAHAN: KHUSUS SATKER level 3
const newArray = [...prevLevels]; currentSelection.wilayah = false;
const currentFileLevels = new Set<number>( currentSelection.polda = false;
newArray[fileIndex] || new Set() currentSelection.polres = false;
); currentSelection.satker = false;
if (value) { // 🔹 Sinkronisasi modal: JANGAN checklist wilayah
// Checklist semua item di modal setFileCheckedLevels((prevLevels) => {
listDest.forEach((item: any) => { const newArray = [...prevLevels];
currentFileLevels.add(Number(item.id)); const currentFileLevels = new Set<number>(
if (item.subDestination) { newArray[fileIndex] || new Set()
item.subDestination.forEach((sub: any) => { );
currentFileLevels.add(Number(sub.id));
});
}
});
} else {
// Unchecklist semua item di modal
currentFileLevels.clear();
}
newArray[fileIndex] = currentFileLevels; if (!value) {
return newArray; currentFileLevels.clear();
}); }
newArray[fileIndex] = currentFileLevels;
return newArray;
});
} else {
// 🔁 LOGIC LAMA (TIDAK DIUBAH)
currentSelection.wilayah = value;
currentSelection.polda = value;
currentSelection.polres = value;
currentSelection.satker = value;
// LOGIC LAMA modal
setFileCheckedLevels((prevLevels) => {
const newArray = [...prevLevels];
const currentFileLevels = new Set<number>(
newArray[fileIndex] || new Set()
);
if (value) {
listDest.forEach((item: any) => {
currentFileLevels.add(Number(item.id));
if (item.subDestination) {
item.subDestination.forEach((sub: any) => {
currentFileLevels.add(Number(sub.id));
});
}
});
} else {
currentFileLevels.clear();
}
newArray[fileIndex] = currentFileLevels;
return newArray;
});
}
} else { } else {
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist // 🔁 SELURUH LOGIC LAMA — TIDAK DISENTUH
// Validasi khusus untuk POLRES
if (key === "polres" && value) { if (key === "polres" && value) {
const currentFileCheckedLevels = fileCheckedLevels[fileIndex]; const currentFileCheckedLevels = fileCheckedLevels[fileIndex];
const hasSelectedPolda = const hasSelectedPolda =
@ -525,14 +552,12 @@ export default function FormImageDetail() {
alert( alert(
"Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES." "Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES."
); );
return prev; // Batalkan perubahan return prev;
} }
} }
// Update salah satu saja
currentSelection[key] = value; currentSelection[key] = value;
// Cek apakah semua selain "semua" sudah dicentang
const allChecked = [ const allChecked = [
"nasional", "nasional",
"wilayah", "wilayah",
@ -550,6 +575,92 @@ export default function FormImageDetail() {
}); });
}; };
// 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;
// // Update fileCheckedLevels untuk sinkronisasi dengan modal
// setFileCheckedLevels((prevLevels) => {
// const newArray = [...prevLevels];
// const currentFileLevels = new Set<number>(
// 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))
// );
// 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) // Fungsi lama untuk kompatibilitas (akan dihapus nanti)
const handleUnitChange = ( const handleUnitChange = (
key: keyof typeof unitSelection, key: keyof typeof unitSelection,
@ -1088,8 +1199,14 @@ export default function FormImageDetail() {
) => { ) => {
let temp = [...filePlacements]; let temp = [...filePlacements];
if (checked) { if (checked) {
// if (placement === "all") {
// temp[index] = ["all", "mabes", "polda", "international"];
if (placement === "all") { if (placement === "all") {
temp[index] = ["all", "mabes", "polda", "international"]; if (isUploadedBySatkerLevel3) {
temp[index] = ["mabes", "international"];
} else {
temp[index] = ["all", "mabes", "polda", "international"];
}
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik // Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik
setFileCheckedLevels((prevLevels) => { setFileCheckedLevels((prevLevels) => {
@ -1359,6 +1476,9 @@ export default function FormImageDetail() {
// console.log("portrai", portraitMap); // console.log("portrai", portraitMap);
}, [portraitMap]); }, [portraitMap]);
const isUploadedBySatkerLevel3 =
Number(detail?.uploadedBy?.userLevel?.levelNumber) === 3;
return ( return (
<form> <form>
{detail !== undefined ? ( {detail !== undefined ? (
@ -1741,6 +1861,56 @@ export default function FormImageDetail() {
key: "international", key: "international",
label: "Internasional", label: "Internasional",
}, },
]
.filter(
(item) =>
!(
isUploadedBySatkerLevel3 &&
item.key === "wilayah"
)
)
.map((item) => (
<div
key={item.key}
className="flex items-center gap-2 p-2 border border-gray-200 rounded-md hover:bg-gray-50"
>
<Checkbox
id={`${item.key}-${index}`}
checked={
fileUnitSelections[index]?.[
item.key as keyof typeof unitSelection
] || false
}
onCheckedChange={(value) => {
handleFileUnitChange(
index,
item.key as keyof typeof unitSelection,
value as boolean
);
setupPlacement(
index,
item.key,
Boolean(value)
);
}}
/>
<Label
htmlFor={`${item.key}-${index}`}
className="text-sm font-medium cursor-pointer"
>
{item.label}
</Label>
</div>
))}
{/* {[
{ key: "semua", label: "Semua" },
{ key: "nasional", label: "Nasional" },
{ key: "wilayah", label: "Wilayah" },
{
key: "international",
label: "Internasional",
},
].map((item, idx) => ( ].map((item, idx) => (
<div <div
key={item.key} key={item.key}
@ -1773,251 +1943,261 @@ export default function FormImageDetail() {
{item.label} {item.label}
</Label> </Label>
</div> </div>
))} ))} */}
</div> </div>
</div> </div>
{/* Detail Wilayah */} {/* Detail Wilayah */}
{fileUnitSelections[index]?.wilayah && ( {fileUnitSelections[index]?.wilayah &&
<div className="border-t border-gray-200 pt-2"> !isUploadedBySatkerLevel3 && (
<p className="text-sm font-medium text-gray-700 mb-2"> <div className="border-t border-gray-200 pt-2">
Detail Wilayah: <p className="text-sm font-medium text-gray-700 mb-2">
</p> Detail Wilayah:
</p>
{/* Checkbox Sub-kategori dengan tombol Kustom sejajar */} {/* Checkbox Sub-kategori dengan tombol Kustom sejajar */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-3"> <div className="grid grid-cols-1 md:grid-cols-4 gap-3">
{[ {[
{ key: "polda", label: "POLDA" }, { key: "polda", label: "POLDA" },
{ key: "polres", label: "POLRES" }, { key: "polres", label: "POLRES" },
{ key: "satker", label: "SATKER" }, { key: "satker", label: "SATKER" },
].map((item, idx) => ( ].map((item, idx) => (
<div <div
key={item.key} key={item.key}
className="flex items-center gap-2 p-3 border border-gray-200 rounded-md hover:bg-gray-50" className="flex items-center gap-2 p-3 border border-gray-200 rounded-md hover:bg-gray-50"
>
<Checkbox
id={`${item.key}-${index}`}
checked={
fileUnitSelections[index]?.[
item.key as keyof typeof unitSelection
] || false
}
onCheckedChange={(value) => {
handleFileUnitChange(
index,
item.key as keyof typeof unitSelection,
value as boolean
);
setupPlacement(
index,
item.key,
Boolean(value)
);
}}
/>
<Label
htmlFor={`${item.key}-${index}`}
className="text-sm font-medium cursor-pointer"
> >
{item.label} <Checkbox
</Label> id={`${item.key}-${index}`}
</div> checked={
))} fileUnitSelections[index]?.[
item.key as keyof typeof unitSelection
{/* Tombol Kustom sejajar dengan checkbox */} ] || false
<div className="flex items-center justify-center p-3"> }
<Dialog> onCheckedChange={(value) => {
<DialogTrigger asChild> handleFileUnitChange(
<Button index,
variant="outline" item.key as keyof typeof unitSelection,
size="sm" value as boolean
className="gap-2" );
setupPlacement(
index,
item.key,
Boolean(value)
);
}}
/>
<Label
htmlFor={`${item.key}-${index}`}
className="text-sm font-medium cursor-pointer"
> >
<Icon {item.label}
icon="material-symbols:tune" </Label>
width={16} </div>
height={16} ))}
/>
{t("custom", {
defaultValue: "Kustom",
})}
</Button>
</DialogTrigger>
<DialogContent className="max-w-[95vw] lg:max-w-[1400px] max-h-[90vh]">
<DialogHeader className="border-b border-gray-200 pb-4">
<DialogTitle className="text-lg font-semibold">
Daftar Wilayah POLDA dan POLRES
</DialogTitle>
</DialogHeader>
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 max-h-[70vh] overflow-y-auto p-1">
{listDest.map((polda: any) => (
<div
key={polda.id}
className="border border-gray-200 rounded-lg p-2 bg-white hover:shadow-sm transition-shadow"
>
{/* Header POLDA */}
<div className="flex items-center justify-between">
<Label className="flex items-center gap-3 flex-1 cursor-pointer">
<Checkbox
checked={
fileCheckedLevels[
index
]?.has(
Number(polda.id)
) || false
}
onCheckedChange={() =>
handleFileCheckboxChangePlacement(
index,
Number(polda.id)
)
}
/>
<span className="font-semibold text-gray-900 text-sm">
{polda.name}
</span>
</Label>
{polda.subDestination && (
<button
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
toggleExpand(
polda.id
);
}}
className="p-1 hover:bg-gray-100 rounded-md transition-colors"
>
<Icon
icon={
expandedPolda[
polda.id
]
? "mdi:chevron-up"
: "mdi:chevron-down"
}
width={16}
height={16}
/>
</button>
)}
</div>
{/* Sub-items */} {/* Tombol Kustom sejajar dengan checkbox */}
{polda.subDestination && <div className="flex items-center justify-center p-3">
expandedPolda[polda.id] && ( <Dialog>
<div className="max-h-[200px] overflow-y-auto border-t border-gray-100 pt-2"> <DialogTrigger asChild>
{/* Tombol Pilih Semua untuk sub-items */} <Button
<div className="mb-2 flex justify-start"> variant="outline"
{(() => { size="sm"
const allSubItemsChecked = className="gap-2"
polda.subDestination?.every( >
(sub: any) => <Icon
fileCheckedLevels[ icon="material-symbols:tune"
index width={16}
]?.has( height={16}
Number( />
sub.id {t("custom", {
) defaultValue: "Kustom",
) })}
); </Button>
return ( </DialogTrigger>
<Button <DialogContent className="max-w-[95vw] lg:max-w-[1400px] max-h-[90vh]">
size="sm" <DialogHeader className="border-b border-gray-200 pb-4">
variant="outline" <DialogTitle className="text-lg font-semibold">
className="text-xs h-6 px-2" Daftar Wilayah POLDA dan
onClick={() => POLRES
handleSelectAllSubItems( </DialogTitle>
index, </DialogHeader>
polda <div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 max-h-[70vh] overflow-y-auto p-1">
) {listDest.map((polda: any) => (
} <div
> key={polda.id}
{allSubItemsChecked ? ( className="border border-gray-200 rounded-lg p-2 bg-white hover:shadow-sm transition-shadow"
<> >
<Icon {/* Header POLDA */}
icon="material-symbols:check-indeterminate-small" <div className="flex items-center justify-between">
width={12} <Label className="flex items-center gap-3 flex-1 cursor-pointer">
height={ <Checkbox
12 checked={
} fileCheckedLevels[
className="mr-1" index
/> ]?.has(
Batal Semua Number(polda.id)
</> ) || false
) : ( }
<> onCheckedChange={() =>
<Icon handleFileCheckboxChangePlacement(
icon="material-symbols:check-all" index,
width={12} Number(polda.id)
height={ )
12 }
} />
className="mr-1" <span className="font-semibold text-gray-900 text-sm">
/> {polda.name}
Pilih Semua </span>
</> </Label>
)} {polda.subDestination && (
</Button> <button
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
toggleExpand(
polda.id
); );
})()} }}
</div> className="p-1 hover:bg-gray-100 rounded-md transition-colors"
<div className="space-y-1"> >
{polda.subDestination.map( <Icon
(sub: any) => ( icon={
<Label expandedPolda[
key={sub.id} polda.id
className="flex items-center gap-2 p-2 rounded-md hover:bg-gray-50 transition-colors cursor-pointer text-xs" ]
> ? "mdi:chevron-up"
<Checkbox : "mdi:chevron-down"
checked={ }
width={16}
height={16}
/>
</button>
)}
</div>
{/* Sub-items */}
{polda.subDestination &&
expandedPolda[
polda.id
] && (
<div className="max-h-[200px] overflow-y-auto border-t border-gray-100 pt-2">
{/* Tombol Pilih Semua untuk sub-items */}
<div className="mb-2 flex justify-start">
{(() => {
const allSubItemsChecked =
polda.subDestination?.every(
(sub: any) =>
fileCheckedLevels[ fileCheckedLevels[
index index
]?.has( ]?.has(
Number( Number(
sub.id sub.id
) )
) || false )
} );
onCheckedChange={() => return (
handleFileCheckboxChangePlacement( <Button
size="sm"
variant="outline"
className="text-xs h-6 px-2"
onClick={() =>
handleSelectAllSubItems(
index, index,
Number( polda
sub.id
)
) )
} }
/> >
<span className="text-gray-700"> {allSubItemsChecked ? (
{sub.name} <>
</span> <Icon
</Label> icon="material-symbols:check-indeterminate-small"
) width={
)} 12
}
height={
12
}
className="mr-1"
/>
Batal
Semua
</>
) : (
<>
<Icon
icon="material-symbols:check-all"
width={
12
}
height={
12
}
className="mr-1"
/>
Pilih
Semua
</>
)}
</Button>
);
})()}
</div>
<div className="space-y-1">
{polda.subDestination.map(
(sub: any) => (
<Label
key={sub.id}
className="flex items-center gap-2 p-2 rounded-md hover:bg-gray-50 transition-colors cursor-pointer text-xs"
>
<Checkbox
checked={
fileCheckedLevels[
index
]?.has(
Number(
sub.id
)
) || false
}
onCheckedChange={() =>
handleFileCheckboxChangePlacement(
index,
Number(
sub.id
)
)
}
/>
<span className="text-gray-700">
{sub.name}
</span>
</Label>
)
)}
</div>
</div> </div>
</div> )}
)} </div>
</div> ))}
))} </div>
</div> <div className="flex justify-end gap-3 border-t border-gray-200 pt-4">
<div className="flex justify-end gap-3 border-t border-gray-200 pt-4"> <DialogClose asChild>
<DialogClose asChild> <Button variant="outline">
<Button variant="outline"> {t("cancel", {
{t("cancel", { defaultValue: "Batal",
defaultValue: "Batal", })}
})} </Button>
</Button> </DialogClose>
</DialogClose> <DialogClose asChild>
<DialogClose asChild> <Button>Simpan</Button>
<Button>Simpan</Button> </DialogClose>
</DialogClose> </div>
</div> </DialogContent>
</DialogContent> </Dialog>
</Dialog> </div>
</div> </div>
</div> </div>
</div> )}
)}
</div> </div>
</div> </div>
) : ( ) : (

View File

@ -207,42 +207,60 @@ export default function FormTeksDetail() {
const currentSelection = { ...newSelections[fileIndex] }; const currentSelection = { ...newSelections[fileIndex] };
if (key === "semua") { if (key === "semua") {
// Jika klik Semua, set semua value ke true/false
currentSelection.semua = value; currentSelection.semua = value;
currentSelection.nasional = value; currentSelection.nasional = value;
currentSelection.wilayah = value;
currentSelection.international = value; currentSelection.international = value;
currentSelection.polda = value;
currentSelection.polres = value;
currentSelection.satker = value;
// Update fileCheckedLevels untuk sinkronisasi dengan modal if (isUploadedBySatkerLevel3) {
setFileCheckedLevels((prevLevels) => { currentSelection.wilayah = false;
const newArray = [...prevLevels]; currentSelection.polda = false;
const currentFileLevels = new Set<number>( currentSelection.polres = false;
newArray[fileIndex] || new Set() currentSelection.satker = false;
);
if (value) { setFileCheckedLevels((prevLevels) => {
// Checklist semua item di modal const newArray = [...prevLevels];
listDest.forEach((item: any) => { const currentFileLevels = new Set<number>(
currentFileLevels.add(Number(item.id)); newArray[fileIndex] || new Set()
if (item.subDestination) { );
item.subDestination.forEach((sub: any) => {
currentFileLevels.add(Number(sub.id));
});
}
});
} else {
// Unchecklist semua item di modal
currentFileLevels.clear();
}
newArray[fileIndex] = currentFileLevels; if (!value) {
return newArray; currentFileLevels.clear();
}); }
newArray[fileIndex] = currentFileLevels;
return newArray;
});
} else {
// 🔁 LOGIC LAMA (TIDAK DIUBAH)
currentSelection.wilayah = value;
currentSelection.polda = value;
currentSelection.polres = value;
currentSelection.satker = value;
setFileCheckedLevels((prevLevels) => {
const newArray = [...prevLevels];
const currentFileLevels = new Set<number>(
newArray[fileIndex] || new Set()
);
if (value) {
listDest.forEach((item: any) => {
currentFileLevels.add(Number(item.id));
if (item.subDestination) {
item.subDestination.forEach((sub: any) => {
currentFileLevels.add(Number(sub.id));
});
}
});
} else {
currentFileLevels.clear();
}
newArray[fileIndex] = currentFileLevels;
return newArray;
});
}
} else { } else {
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist
if (key === "polres" && value) { if (key === "polres" && value) {
const currentFileCheckedLevels = fileCheckedLevels[fileIndex]; const currentFileCheckedLevels = fileCheckedLevels[fileIndex];
const hasSelectedPolda = const hasSelectedPolda =
@ -258,14 +276,12 @@ export default function FormTeksDetail() {
alert( alert(
"Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES." "Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES."
); );
return prev; // Batalkan perubahan return prev;
} }
} }
// Update salah satu saja
currentSelection[key] = value; currentSelection[key] = value;
// Cek apakah semua selain "semua" sudah dicentang
const allChecked = [ const allChecked = [
"nasional", "nasional",
"wilayah", "wilayah",
@ -283,6 +299,92 @@ export default function FormTeksDetail() {
}); });
}; };
// 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;
// // Update fileCheckedLevels untuk sinkronisasi dengan modal
// setFileCheckedLevels((prevLevels) => {
// const newArray = [...prevLevels];
// const currentFileLevels = new Set<number>(
// 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))
// );
// 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;
// });
// };
let fileTypeId = "3"; let fileTypeId = "3";
const toggleExpand = (id: number) => { const toggleExpand = (id: number) => {
@ -725,8 +827,15 @@ export default function FormTeksDetail() {
) => { ) => {
let temp = [...filePlacements]; let temp = [...filePlacements];
if (checked) { if (checked) {
// if (placement === "all") {
// temp[index] = ["all", "mabes", "polda", "international"];
if (placement === "all") { if (placement === "all") {
temp[index] = ["all", "mabes", "polda", "international"]; if (isUploadedBySatkerLevel3) {
temp[index] = ["mabes", "international"];
} else {
temp[index] = ["all", "mabes", "polda", "international"];
}
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik // Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik
setFileCheckedLevels((prevLevels) => { setFileCheckedLevels((prevLevels) => {
@ -1126,6 +1235,9 @@ export default function FormTeksDetail() {
}); });
}; };
const isUploadedBySatkerLevel3 =
Number(detail?.uploadedBy?.userLevel?.levelNumber) === 3;
return ( return (
<form> <form>
{detail !== undefined ? ( {detail !== undefined ? (
@ -1471,6 +1583,56 @@ export default function FormTeksDetail() {
key: "international", key: "international",
label: "Internasional", label: "Internasional",
}, },
]
.filter(
(item) =>
!(
isUploadedBySatkerLevel3 &&
item.key === "wilayah"
)
)
.map((item) => (
<div
key={item.key}
className="flex items-center gap-2 p-2 border border-gray-200 rounded-md hover:bg-gray-50"
>
<Checkbox
id={`${item.key}-${index}`}
checked={
fileUnitSelections[index]?.[
item.key as keyof typeof unitSelection
] || false
}
onCheckedChange={(value) => {
handleFileUnitChange(
index,
item.key as keyof typeof unitSelection,
value as boolean
);
setupPlacement(
index,
item.key,
Boolean(value)
);
}}
/>
<Label
htmlFor={`${item.key}-${index}`}
className="text-sm font-medium cursor-pointer"
>
{item.label}
</Label>
</div>
))}
{/* {[
{ key: "semua", label: "Semua" },
{ key: "nasional", label: "Nasional" },
{ key: "wilayah", label: "Wilayah" },
{
key: "international",
label: "Internasional",
},
].map((item, idx) => ( ].map((item, idx) => (
<div <div
key={item.key} key={item.key}
@ -1503,7 +1665,7 @@ export default function FormTeksDetail() {
{item.label} {item.label}
</Label> </Label>
</div> </div>
))} ))} */}
</div> </div>
</div> </div>

View File

@ -210,42 +210,60 @@ export default function FormVideoDetail() {
const currentSelection = { ...newSelections[fileIndex] }; const currentSelection = { ...newSelections[fileIndex] };
if (key === "semua") { if (key === "semua") {
// Jika klik Semua, set semua value ke true/false
currentSelection.semua = value; currentSelection.semua = value;
currentSelection.nasional = value; currentSelection.nasional = value;
currentSelection.wilayah = value;
currentSelection.international = value; currentSelection.international = value;
currentSelection.polda = value;
currentSelection.polres = value;
currentSelection.satker = value;
// Update fileCheckedLevels untuk sinkronisasi dengan modal if (isUploadedBySatkerLevel3) {
setFileCheckedLevels((prevLevels) => { currentSelection.wilayah = false;
const newArray = [...prevLevels]; currentSelection.polda = false;
const currentFileLevels = new Set<number>( currentSelection.polres = false;
newArray[fileIndex] || new Set() currentSelection.satker = false;
);
if (value) { setFileCheckedLevels((prevLevels) => {
// Checklist semua item di modal const newArray = [...prevLevels];
listDest.forEach((item: any) => { const currentFileLevels = new Set<number>(
currentFileLevels.add(Number(item.id)); newArray[fileIndex] || new Set()
if (item.subDestination) { );
item.subDestination.forEach((sub: any) => {
currentFileLevels.add(Number(sub.id));
});
}
});
} else {
// Unchecklist semua item di modal
currentFileLevels.clear();
}
newArray[fileIndex] = currentFileLevels; if (!value) {
return newArray; currentFileLevels.clear();
}); }
newArray[fileIndex] = currentFileLevels;
return newArray;
});
} else {
// 🔁 LOGIC LAMA (TIDAK DIUBAH)
currentSelection.wilayah = value;
currentSelection.polda = value;
currentSelection.polres = value;
currentSelection.satker = value;
setFileCheckedLevels((prevLevels) => {
const newArray = [...prevLevels];
const currentFileLevels = new Set<number>(
newArray[fileIndex] || new Set()
);
if (value) {
listDest.forEach((item: any) => {
currentFileLevels.add(Number(item.id));
if (item.subDestination) {
item.subDestination.forEach((sub: any) => {
currentFileLevels.add(Number(sub.id));
});
}
});
} else {
currentFileLevels.clear();
}
newArray[fileIndex] = currentFileLevels;
return newArray;
});
}
} else { } else {
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist
if (key === "polres" && value) { if (key === "polres" && value) {
const currentFileCheckedLevels = fileCheckedLevels[fileIndex]; const currentFileCheckedLevels = fileCheckedLevels[fileIndex];
const hasSelectedPolda = const hasSelectedPolda =
@ -261,14 +279,12 @@ export default function FormVideoDetail() {
alert( alert(
"Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES." "Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES."
); );
return prev; // Batalkan perubahan return prev;
} }
} }
// Update salah satu saja
currentSelection[key] = value; currentSelection[key] = value;
// Cek apakah semua selain "semua" sudah dicentang
const allChecked = [ const allChecked = [
"nasional", "nasional",
"wilayah", "wilayah",
@ -286,6 +302,92 @@ export default function FormVideoDetail() {
}); });
}; };
// 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;
// // Update fileCheckedLevels untuk sinkronisasi dengan modal
// setFileCheckedLevels((prevLevels) => {
// const newArray = [...prevLevels];
// const currentFileLevels = new Set<number>(
// 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))
// );
// 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;
// });
// };
let fileTypeId = "2"; let fileTypeId = "2";
const toggleExpand = (id: number) => { const toggleExpand = (id: number) => {
@ -690,8 +792,15 @@ export default function FormVideoDetail() {
) => { ) => {
let temp = [...filePlacements]; let temp = [...filePlacements];
if (checked) { if (checked) {
// if (placement === "all") {
// temp[index] = ["all", "mabes", "polda", "international"];
if (placement === "all") { if (placement === "all") {
temp[index] = ["all", "mabes", "polda", "international"]; if (isUploadedBySatkerLevel3) {
temp[index] = ["mabes", "international"];
} else {
temp[index] = ["all", "mabes", "polda", "international"];
}
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik // Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik
setFileCheckedLevels((prevLevels) => { setFileCheckedLevels((prevLevels) => {
@ -1128,6 +1237,9 @@ export default function FormVideoDetail() {
}); });
}; };
const isUploadedBySatkerLevel3 =
Number(detail?.uploadedBy?.userLevel?.levelNumber) === 3;
return ( return (
<form> <form>
{detail !== undefined ? ( {detail !== undefined ? (
@ -1475,6 +1587,56 @@ export default function FormVideoDetail() {
key: "international", key: "international",
label: "Internasional", label: "Internasional",
}, },
]
.filter(
(item) =>
!(
isUploadedBySatkerLevel3 &&
item.key === "wilayah"
)
)
.map((item) => (
<div
key={item.key}
className="flex items-center gap-2 p-2 border border-gray-200 rounded-md hover:bg-gray-50"
>
<Checkbox
id={`${item.key}-${index}`}
checked={
fileUnitSelections[index]?.[
item.key as keyof typeof unitSelection
] || false
}
onCheckedChange={(value) => {
handleFileUnitChange(
index,
item.key as keyof typeof unitSelection,
value as boolean
);
setupPlacement(
index,
item.key,
Boolean(value)
);
}}
/>
<Label
htmlFor={`${item.key}-${index}`}
className="text-sm font-medium cursor-pointer"
>
{item.label}
</Label>
</div>
))}
{/* {[
{ key: "semua", label: "Semua" },
{ key: "nasional", label: "Nasional" },
{ key: "wilayah", label: "Wilayah" },
{
key: "international",
label: "Internasional",
},
].map((item, idx) => ( ].map((item, idx) => (
<div <div
key={item.key} key={item.key}
@ -1507,256 +1669,266 @@ export default function FormVideoDetail() {
{item.label} {item.label}
</Label> </Label>
</div> </div>
))} ))} */}
</div> </div>
</div> </div>
{/* Detail Wilayah */} {/* Detail Wilayah */}
{fileUnitSelections[index]?.wilayah && ( {fileUnitSelections[index]?.wilayah &&
<div className="border-t border-gray-200 pt-2"> !isUploadedBySatkerLevel3 && (
<p className="text-sm font-medium text-gray-700 mb-2"> <div className="border-t border-gray-200 pt-2">
Detail Wilayah: <p className="text-sm font-medium text-gray-700 mb-2">
</p> Detail Wilayah:
</p>
{/* Checkbox Sub-kategori dengan tombol Kustom sejajar */} {/* Checkbox Sub-kategori dengan tombol Kustom sejajar */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-3"> <div className="grid grid-cols-1 md:grid-cols-4 gap-3">
{[ {[
{ key: "polda", label: "POLDA" }, { key: "polda", label: "POLDA" },
{ key: "polres", label: "POLRES" }, { key: "polres", label: "POLRES" },
{ key: "satker", label: "SATKER" }, { key: "satker", label: "SATKER" },
].map((item, idx) => ( ].map((item, idx) => (
<div <div
key={item.key} key={item.key}
className="flex items-center gap-2 p-3 border border-gray-200 rounded-md hover:bg-gray-50" className="flex items-center gap-2 p-3 border border-gray-200 rounded-md hover:bg-gray-50"
>
<Checkbox
id={`${item.key}-${index}`}
checked={
fileUnitSelections[index]?.[
item.key as keyof typeof unitSelection
] || false
}
onCheckedChange={(value) => {
handleFileUnitChange(
index,
item.key as keyof typeof unitSelection,
value as boolean
);
setupPlacement(
index,
item.key,
Boolean(value)
);
}}
/>
<Label
htmlFor={`${item.key}-${index}`}
className="text-sm font-medium cursor-pointer"
> >
{item.label} <Checkbox
</Label> id={`${item.key}-${index}`}
</div> checked={
))} fileUnitSelections[index]?.[
item.key as keyof typeof unitSelection
{/* Tombol Kustom sejajar dengan checkbox */} ] || false
<div className="flex items-center justify-center p-3"> }
<Dialog> onCheckedChange={(value) => {
<DialogTrigger asChild> handleFileUnitChange(
<Button index,
variant="outline" item.key as keyof typeof unitSelection,
size="sm" value as boolean
className="gap-2" );
setupPlacement(
index,
item.key,
Boolean(value)
);
}}
/>
<Label
htmlFor={`${item.key}-${index}`}
className="text-sm font-medium cursor-pointer"
> >
<Icon {item.label}
icon="material-symbols:tune" </Label>
width={16} </div>
height={16} ))}
/>
{t("custom", {
defaultValue: "Kustom",
})}
</Button>
</DialogTrigger>
<DialogContent className="max-w-[95vw] lg:max-w-[1400px] max-h-[90vh]">
<DialogHeader className="border-b border-gray-200 pb-4">
<DialogTitle className="text-lg font-semibold">
Daftar Wilayah POLDA dan POLRES
</DialogTitle>
</DialogHeader>
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 max-h-[70vh] overflow-y-auto p-1">
{listDest.map((polda: any) => (
<div
key={polda.id}
className="border border-gray-200 rounded-lg p-2 bg-white hover:shadow-sm transition-shadow"
>
{/* Header POLDA */}
<div className="flex items-center justify-between">
<Label className="flex items-center gap-3 flex-1 cursor-pointer">
<Checkbox
checked={
fileCheckedLevels[
index
]?.has(
Number(polda.id)
) || false
}
onCheckedChange={() =>
handleFileCheckboxChangePlacement(
index,
Number(polda.id)
)
}
/>
<span className="font-semibold text-gray-900 text-sm">
{polda.name}
</span>
</Label>
{polda.subDestination && (
<button
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
toggleExpand(
polda.id
);
}}
className="p-1 hover:bg-gray-100 rounded-md transition-colors"
>
<Icon
icon={
expandedPolda[
polda.id
]
? "mdi:chevron-up"
: "mdi:chevron-down"
}
width={16}
height={16}
/>
</button>
)}
</div>
{/* Sub-items */} {/* Tombol Kustom sejajar dengan checkbox */}
{polda.subDestination && <div className="flex items-center justify-center p-3">
expandedPolda[polda.id] && ( <Dialog>
<div className="max-h-[200px] overflow-y-auto border-t border-gray-100 pt-2"> <DialogTrigger asChild>
{/* Tombol Pilih Semua untuk sub-items */} <Button
<div className="mb-2 flex justify-start"> variant="outline"
{(() => { size="sm"
const allSubItemsChecked = className="gap-2"
polda.subDestination?.every( >
(sub: any) => <Icon
fileCheckedLevels[ icon="material-symbols:tune"
index width={16}
]?.has( height={16}
Number( />
sub.id {t("custom", {
) defaultValue: "Kustom",
) })}
); </Button>
return ( </DialogTrigger>
<Button <DialogContent className="max-w-[95vw] lg:max-w-[1400px] max-h-[90vh]">
size="sm" <DialogHeader className="border-b border-gray-200 pb-4">
variant="outline" <DialogTitle className="text-lg font-semibold">
className="text-xs h-6 px-2" Daftar Wilayah POLDA dan
onClick={() => POLRES
handleSelectAllSubItems( </DialogTitle>
index, </DialogHeader>
polda <div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-4 max-h-[70vh] overflow-y-auto p-1">
) {listDest.map((polda: any) => (
} <div
> key={polda.id}
{allSubItemsChecked ? ( className="border border-gray-200 rounded-lg p-2 bg-white hover:shadow-sm transition-shadow"
<> >
<Icon {/* Header POLDA */}
icon="material-symbols:check-indeterminate-small" <div className="flex items-center justify-between">
width={12} <Label className="flex items-center gap-3 flex-1 cursor-pointer">
height={ <Checkbox
12 checked={
} fileCheckedLevels[
className="mr-1" index
/> ]?.has(
Batal Semua Number(polda.id)
</> ) || false
) : ( }
<> onCheckedChange={() =>
<Icon handleFileCheckboxChangePlacement(
icon="material-symbols:check-all" index,
width={12} Number(polda.id)
height={ )
12 }
} />
className="mr-1" <span className="font-semibold text-gray-900 text-sm">
/> {polda.name}
Pilih Semua </span>
</> </Label>
)} {polda.subDestination && (
</Button> <button
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
toggleExpand(
polda.id
); );
})()} }}
</div> className="p-1 hover:bg-gray-100 rounded-md transition-colors"
<div className="space-y-1"> >
{polda.subDestination.map( <Icon
(sub: any) => ( icon={
<Label expandedPolda[
key={sub.id} polda.id
className="flex items-center gap-2 p-2 rounded-md hover:bg-gray-50 transition-colors cursor-pointer text-xs" ]
> ? "mdi:chevron-up"
<Checkbox : "mdi:chevron-down"
checked={ }
width={16}
height={16}
/>
</button>
)}
</div>
{/* Sub-items */}
{polda.subDestination &&
expandedPolda[
polda.id
] && (
<div className="max-h-[200px] overflow-y-auto border-t border-gray-100 pt-2">
{/* Tombol Pilih Semua untuk sub-items */}
<div className="mb-2 flex justify-start">
{(() => {
const allSubItemsChecked =
polda.subDestination?.every(
(sub: any) =>
fileCheckedLevels[ fileCheckedLevels[
index index
]?.has( ]?.has(
Number( Number(
sub.id sub.id
) )
) || false )
} );
onCheckedChange={() => return (
handleFileCheckboxChangePlacement( <Button
size="sm"
variant="outline"
className="text-xs h-6 px-2"
onClick={() =>
handleSelectAllSubItems(
index, index,
Number( polda
sub.id
)
) )
} }
/> >
<span className="text-gray-700"> {allSubItemsChecked ? (
{sub.name} <>
</span> <Icon
</Label> icon="material-symbols:check-indeterminate-small"
) width={
)} 12
}
height={
12
}
className="mr-1"
/>
Batal
Semua
</>
) : (
<>
<Icon
icon="material-symbols:check-all"
width={
12
}
height={
12
}
className="mr-1"
/>
Pilih
Semua
</>
)}
</Button>
);
})()}
</div>
<div className="space-y-1">
{polda.subDestination.map(
(sub: any) => (
<Label
key={sub.id}
className="flex items-center gap-2 p-2 rounded-md hover:bg-gray-50 transition-colors cursor-pointer text-xs"
>
<Checkbox
checked={
fileCheckedLevels[
index
]?.has(
Number(
sub.id
)
) || false
}
onCheckedChange={() =>
handleFileCheckboxChangePlacement(
index,
Number(
sub.id
)
)
}
/>
<span className="text-gray-700">
{sub.name}
</span>
</Label>
)
)}
</div>
</div> </div>
</div> )}
)} </div>
</div> ))}
))} </div>
</div> <div className="flex justify-end gap-3 border-t border-gray-200 pt-4">
<div className="flex justify-end gap-3 border-t border-gray-200 pt-4"> <DialogClose asChild>
<DialogClose asChild> <Button variant="outline">
<Button variant="outline"> {t("cancel", {
{t("cancel", { defaultValue: "Batal",
defaultValue: "Batal", })}
})} </Button>
</Button> </DialogClose>
</DialogClose> <DialogClose asChild>
<DialogClose asChild> <Button>
<Button> {/* {t("save", {
{/* {t("save", {
defaultValue: "Simpan", defaultValue: "Simpan",
})} */} })} */}
Simpan Simpan
</Button> </Button>
</DialogClose> </DialogClose>
</div> </div>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</div>
</div> </div>
</div> </div>
</div> )}
)}
</div> </div>
</div> </div>
) : ( ) : (