update : selection box user levels

This commit is contained in:
hanif salafi 2025-08-19 07:54:40 +07:00
parent 24a5e2a5c1
commit c12dbf1596
2 changed files with 3783 additions and 5 deletions

View File

@ -118,9 +118,9 @@ export default function FormContestDetail() {
const [detail, setDetail] = useState<any>();
const [refresh] = useState(false);
const [date, setDate] = useState<DateRange | undefined>();
const [listDest, setListDest] = useState([]);
const [checkedLevels, setCheckedLevels] = useState(new Set());
const [expandedPolda, setExpandedPolda] = useState([{}]);
const [listDest, setListDest] = useState<any[]>([]);
const [checkedLevels, setCheckedLevels] = useState<Set<number>>(new Set());
const [expandedPolda, setExpandedPolda] = useState<Record<number, boolean>>({});
const [isLoading, setIsLoading] = useState(false);
const [audioFile, setAudioFile] = useState<File | null>(null);
const [imageFiles, setImageFiles] = useState<FileWithPreview[]>([]);
@ -153,6 +153,11 @@ export default function FormContestDetail() {
satker: false,
});
// State untuk melacak apakah perubahan berasal dari checkbox Pelaksana Tugas
const [isUpdatingFromPelaksana, setIsUpdatingFromPelaksana] = useState(false);
// State untuk melacak jenis perubahan spesifik
const [pelaksanaChangeType, setPelaksanaChangeType] = useState<string>("");
const {
control,
handleSubmit,
@ -192,6 +197,16 @@ export default function FormContestDetail() {
fetchPoldaPolres();
}, []);
// useEffect untuk sinkronisasi checkbox modal dengan Pelaksana Tugas
// Ketika unitSelection berubah dari checkbox Pelaksana Tugas:
// - Jika di-checklist: checklist semua item sesuai kategori di modal
// - Jika di-unchecklist: unchecklist semua item di modal
useEffect(() => {
if (listDest.length > 0) {
syncModalWithUnitSelection();
}
}, [unitSelection, listDest]);
useEffect(() => {
async function initState() {
if (id) {
@ -237,6 +252,61 @@ export default function FormContestDetail() {
}
}, [detail?.targetOutput]);
// Fungsi untuk update unitSelection berdasarkan checkbox modal
// Checkbox di Pelaksana Tugas hanya akan aktif jika SEMUA item dalam kategori tersebut dichecklist
const updateUnitSelectionFromModal = (levelId: number) => {
setTimeout(() => {
// Hitung total item yang tersedia untuk setiap kategori
const totalPolda = listDest.filter((item: any) =>
item.levelNumber === 2 && item.name !== "SATKER POLRI"
).length;
const totalPolres = listDest.reduce((total: number, item: any) => {
if (item.subDestination) {
return total + item.subDestination.length;
}
return total;
}, 0);
const satkerItem = listDest.find((item: any) => item.name === "SATKER POLRI");
const totalSatker = satkerItem ? (1 + (satkerItem.subDestination?.length || 0)) : 0;
// Hitung item yang dichecklist untuk setiap kategori
const checkedPoldaCount = listDest.filter((item: any) =>
item.levelNumber === 2 &&
item.name !== "SATKER POLRI" &&
checkedLevels.has(item.id)
).length;
const checkedPolresCount = listDest.reduce((total: number, item: any) => {
if (item.subDestination) {
return total + item.subDestination.filter((sub: any) => checkedLevels.has(sub.id)).length;
}
return total;
}, 0);
const checkedSatkerCount = satkerItem ? (
(checkedLevels.has(satkerItem.id) ? 1 : 0) +
(satkerItem.subDestination?.filter((sub: any) => checkedLevels.has(sub.id)).length || 0)
) : 0;
// Checkbox hanya aktif jika SEMUA item dalam kategori tersebut dichecklist
const hasCheckedPolda = totalPolda > 0 && checkedPoldaCount === totalPolda;
const hasCheckedPolres = totalPolres > 0 && checkedPolresCount === totalPolres;
const hasCheckedSatker = totalSatker > 0 && checkedSatkerCount === totalSatker;
// Update unitSelection berdasarkan checkbox yang aktif di modal
setUnitSelection(prev => ({
...prev,
polda: hasCheckedPolda,
polres: hasCheckedPolres,
satker: hasCheckedSatker,
// allUnit hanya true jika semua kategori terpenuhi
allUnit: hasCheckedPolda && hasCheckedPolres && hasCheckedSatker
}));
}, 0);
};
const handleCheckboxChange = (levelId: number) => {
setCheckedLevels((prev) => {
const updatedLevels = new Set(prev);
@ -247,6 +317,85 @@ export default function FormContestDetail() {
}
return updatedLevels;
});
// Update unitSelection berdasarkan perubahan di modal
updateUnitSelectionFromModal(levelId);
};
// Fungsi untuk sinkronisasi checkbox modal dengan Pelaksana Tugas
const syncModalWithUnitSelection = () => {
// Hanya jalankan sinkronisasi jika perubahan berasal dari checkbox Pelaksana Tugas
if (isUpdatingFromPelaksana) {
// Khusus untuk unchecklist POLRES: hanya unchecklist polres, pertahankan polda
if (pelaksanaChangeType === "polres_unchecked") {
const newCheckedLevels = new Set<number>(checkedLevels);
// Hapus semua polres dari modal, tapi pertahankan polda
listDest.forEach((item: any) => {
if (item.subDestination && item.levelNumber === 2 && item.name !== "SATKER POLRI") {
item.subDestination.forEach((polres: any) => {
newCheckedLevels.delete(polres.id);
});
}
});
setCheckedLevels(newCheckedLevels);
}
// Untuk perubahan lainnya, jalankan logika normal
else if (unitSelection.polda || unitSelection.polres || unitSelection.satker) {
// Mulai dengan checkbox yang sudah ada untuk mempertahankan pilihan manual user
const newCheckedLevels = new Set<number>(checkedLevels);
listDest.forEach((item: any) => {
// Jika polda dichecklist, checklist semua polda (levelNumber 2, bukan SATKER POLRI)
if (unitSelection.polda && item.levelNumber === 2 && item.name !== "SATKER POLRI") {
newCheckedLevels.add(item.id);
}
// Jika satker dichecklist, checklist SATKER POLRI dan sub-itemnya
if (unitSelection.satker && item.name === "SATKER POLRI") {
newCheckedLevels.add(item.id);
if (item.subDestination) {
item.subDestination.forEach((sub: any) => {
newCheckedLevels.add(sub.id);
});
}
}
// Jika polres dichecklist
if (unitSelection.polres && item.subDestination) {
// Jika checkbox POLDA di Pelaksana Tugas juga aktif, checklist semua polres
if (unitSelection.polda && item.levelNumber === 2 && item.name !== "SATKER POLRI") {
item.subDestination.forEach((polres: any) => {
newCheckedLevels.add(polres.id);
});
}
// Jika checkbox POLDA di Pelaksana Tugas tidak aktif, tapi ada POLDA yang dichecklist di modal
else if (!unitSelection.polda && item.levelNumber === 2 && item.name !== "SATKER POLRI") {
// Cek apakah POLDA ini sudah dichecklist di modal
if (checkedLevels.has(item.id)) {
// Jika ya, checklist semua polres dari POLDA ini
item.subDestination.forEach((polres: any) => {
newCheckedLevels.add(polres.id);
});
}
}
}
});
setCheckedLevels(newCheckedLevels);
} else {
// Jika tidak ada unitSelection yang aktif, unchecklist semua item di modal
// Setelah itu user bisa checklist secara manual
setCheckedLevels(new Set<number>());
}
// Reset flag setelah sinkronisasi selesai
setTimeout(() => {
setIsUpdatingFromPelaksana(false);
setPelaksanaChangeType("");
}, 100);
}
};
const handlePoldaPolresChange = () => {
@ -706,6 +855,10 @@ export default function FormContestDetail() {
id={key}
checked={unitSelection[key as keyof typeof unitSelection]}
onCheckedChange={(value) => {
// Set flag bahwa perubahan berasal dari checkbox Pelaksana Tugas
setIsUpdatingFromPelaksana(true);
setPelaksanaChangeType(key + (value ? "_checked" : "_unchecked"));
if (key === "allUnit") {
const newValue = Boolean(value);
setUnitSelection({
@ -716,6 +869,22 @@ export default function FormContestDetail() {
satker: newValue,
});
} else {
// Validasi khusus untuk POLRES
if (key === "polres" && value) {
// Cek apakah ada POLDA yang sudah dichecklist di modal
const hasCheckedPolda = listDest.some((item: any) =>
item.levelNumber === 2 &&
item.name !== "SATKER POLRI" &&
checkedLevels.has(item.id)
);
if (!hasCheckedPolda) {
// Jika tidak ada POLDA yang dichecklist di modal, tampilkan peringatan dan batalkan
alert("Harap pilih POLDA di Modal List terlebih dahulu sebelum mengaktifkan checkbox POLRES.");
return; // Batalkan perubahan
}
}
setUnitSelection((prev) => {
const updated = { ...prev, [key]: Boolean(value) };
// Update 'allUnit' jika semua sub-checkbox true
@ -758,7 +927,12 @@ export default function FormContestDetail() {
/>
{polda.name}
<button
onClick={() => toggleExpand(polda.id)}
type="button"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
toggleExpand(polda.id);
}}
className="ml-2 focus:outline-none"
>
{expandedPolda[polda.id] ? (
@ -790,10 +964,60 @@ export default function FormContestDetail() {
}
);
setCheckedLevels(updatedLevels);
// Update unitSelection berdasarkan perubahan
setTimeout(() => {
// Hitung total item yang tersedia untuk setiap kategori
const totalPolda = listDest.filter((item: any) =>
item.levelNumber === 2 && item.name !== "SATKER POLRI"
).length;
const totalPolres = listDest.reduce((total: number, item: any) => {
if (item.subDestination) {
return total + item.subDestination.length;
}
return total;
}, 0);
const satkerItem = listDest.find((item: any) => item.name === "SATKER POLRI");
const totalSatker = satkerItem ? (1 + (satkerItem.subDestination?.length || 0)) : 0;
// Hitung item yang dichecklist untuk setiap kategori
const checkedPoldaCount = listDest.filter((item: any) =>
item.levelNumber === 2 &&
item.name !== "SATKER POLRI" &&
updatedLevels.has(item.id)
).length;
const checkedPolresCount = listDest.reduce((total: number, item: any) => {
if (item.subDestination) {
return total + item.subDestination.filter((sub: any) => updatedLevels.has(sub.id)).length;
}
return total;
}, 0);
const checkedSatkerCount = satkerItem ? (
(updatedLevels.has(satkerItem.id) ? 1 : 0) +
(satkerItem.subDestination?.filter((sub: any) => updatedLevels.has(sub.id)).length || 0)
) : 0;
// Checkbox hanya aktif jika SEMUA item dalam kategori tersebut dichecklist
const hasCheckedPolda = totalPolda > 0 && checkedPoldaCount === totalPolda;
const hasCheckedPolres = totalPolres > 0 && checkedPolresCount === totalPolres;
const hasCheckedSatker = totalSatker > 0 && checkedSatkerCount === totalSatker;
setUnitSelection(prev => ({
...prev,
polda: hasCheckedPolda,
polres: hasCheckedPolres,
satker: hasCheckedSatker,
allUnit: hasCheckedPolda && hasCheckedPolres && hasCheckedSatker
}));
}, 0);
}}
className="mr-2"
/>
Pilih Semua Polres
Pilih Semua
</Label>
{polda?.subDestination?.map((polres: any) => (
<Label key={polres.id} className="block mt-1">

File diff suppressed because it is too large Load Diff