fix conflict pull main

This commit is contained in:
Sabda Yagra 2025-09-11 09:04:55 +07:00
commit fdb2a161f6
4 changed files with 4161 additions and 682 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@ import {
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { register } from "module";
import { Switch } from "@/components/ui/switch";
@ -35,7 +36,9 @@ import {
getTagsBySubCategoryId,
listEnableCategory,
uploadThumbnail,
updateFilePlacements,
} from "@/service/content/content";
import { getUserLevelForAssignments } from "@/service/task";
import { detailMedia } from "@/service/curated-content/curated-content";
import { Badge } from "@/components/ui/badge";
import { CloudUpload, MailIcon } from "lucide-react";
@ -57,6 +60,7 @@ import { error, loading } from "@/lib/swal";
import { useTranslations } from "next-intl";
import dynamic from "next/dynamic";
import { htmlToString } from "@/utils/globals";
import { v4 as uuidv4 } from "uuid";
const videoSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
@ -97,6 +101,35 @@ type Option = {
name: string;
};
type PlacementType = "all" | "mabes" | "wilayah" | "polda" | "satker" | "international";
interface FilePlacement {
id: string;
placements: PlacementType[];
}
interface TempFileItem {
id: string;
fileName: string;
url: string;
thumbnailFileUrl: string;
placements: string;
customLocationPlacements: string;
}
interface Destination {
id: number;
name: string;
levelNumber: number;
subDestination: SubDestination[];
}
interface SubDestination {
id: number;
name: string;
levelNumber: number;
}
const CustomEditor = dynamic(
() => {
return import("@/components/editor/custom-editor");
@ -132,17 +165,42 @@ export default function FormVideoUpdate() {
const [thumbsSwiper, setThumbsSwiper] = useState<any>(null);
const [files, setFiles] = useState<FileWithPreview[]>([]);
const [selectedTarget, setSelectedTarget] = useState("");
const [unitSelection, setUnitSelection] = useState({
allUnit: false,
mabes: false,
polda: false,
polres: false,
});
const [publishedFor, setPublishedFor] = useState<string[]>([]);
const inputRef = useRef<HTMLInputElement>(null);
const [selectedOptions, setSelectedOptions] = useState<{
[fileId: number]: string[];
}>({});
const [fileUnitSelections, setFileUnitSelections] = useState<{
[fileId: string]: {
semua: boolean;
nasional: boolean;
wilayah: boolean;
international: boolean;
polda: boolean;
satker: boolean;
};
}>({});
const [unitSelection, setUnitSelection] = useState({
semua: false,
nasional: false,
wilayah: false,
international: false,
polda: false,
satker: false,
});
const [checkedLevels, setCheckedLevels] = useState<Set<number>>(new Set());
const [listDest, setListDest] = useState<Destination[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [expandedPolda, setExpandedPolda] = useState<Set<number>>(new Set());
const [fileCheckedLevels, setFileCheckedLevels] = useState<{
[fileId: string]: Set<number>;
}>({});
const [isUpdatingFromMainCheckbox, setIsUpdatingFromMainCheckbox] = useState(false);
const [mainCheckboxChangeType, setMainCheckboxChangeType] = useState<string | null>(null);
const [filePlacements, setFilePlacements] = useState<{
[fileId: string]: PlacementType[];
}>({});
const [tempFile, setTempFile] = useState<TempFileItem | null>(null);
const options: Option[] = [
{ id: "all", name: "SEMUA" },
@ -156,7 +214,10 @@ export default function FormVideoUpdate() {
const { getRootProps, getInputProps } = useDropzone({
onDrop: (acceptedFiles) => {
setFiles(acceptedFiles.map((file) => Object.assign(file)));
setFiles(acceptedFiles.map((file) => Object.assign(file, {
id: uuidv4(),
preview: URL.createObjectURL(file)
})));
},
accept: {
"video/*": [],
@ -203,6 +264,36 @@ export default function FormVideoUpdate() {
initState();
}, []);
useEffect(() => {
const fetchPoldaPolres = async () => {
try {
setIsLoading(true);
const response = await getUserLevelForAssignments();
if (response?.data?.data) {
setListDest(response.data.data.list);
}
} catch (error) {
console.error("Error fetching user levels:", error);
} finally {
setIsLoading(false);
}
};
fetchPoldaPolres();
}, []);
useEffect(() => {
if (isUpdatingFromMainCheckbox && mainCheckboxChangeType) {
syncModalWithMainCheckbox();
setIsUpdatingFromMainCheckbox(false);
setMainCheckboxChangeType(null);
}
}, [isUpdatingFromMainCheckbox, mainCheckboxChangeType]);
useEffect(() => {
updateMainCheckboxFromModalLegacy();
}, [checkedLevels]);
const handleAddTag = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter" && e.currentTarget.value.trim()) {
e.preventDefault();
@ -274,13 +365,43 @@ export default function FormVideoUpdate() {
if (details?.files) {
setFiles(details.files);
const initialOptions: { [key: number]: string[] } = {};
// Initialize filePlacements
const initialFilePlacements: { [key: string]: PlacementType[] } = {};
details.files.forEach((file: any) => {
if (file.placements) {
initialOptions[file.id] = mapPlacementsToOptions(file.placements);
const placements = file.placements.split(",").map((p: string) => p.trim() as PlacementType);
initialFilePlacements[file.id] = placements;
}
});
setSelectedOptions(initialOptions);
setFilePlacements(initialFilePlacements);
// Initialize fileCheckedLevels
const initialFileCheckedLevels: { [key: string]: Set<number> } = {};
details.files.forEach((file: any) => {
if (file.customLocationPlacements) {
const levelIds = file.customLocationPlacements.split(",").map((id: string) => parseInt(id.trim()));
initialFileCheckedLevels[file.id] = new Set(levelIds);
}
});
setFileCheckedLevels(initialFileCheckedLevels);
// Initialize fileUnitSelections
const initialFileUnitSelections: { [key: string]: any } = {};
details.files.forEach((file: any) => {
if (file.placements) {
const placements = file.placements.split(",").map((p: string) => p.trim());
initialFileUnitSelections[file.id] = {
semua: placements.includes("all"),
nasional: placements.includes("mabes"),
wilayah: placements.includes("wilayah") || placements.includes("polda") || placements.includes("satker"),
international: placements.includes("international"),
polda: placements.includes("polda"),
satker: placements.includes("satker"),
};
}
});
setFileUnitSelections(initialFileUnitSelections);
}
if (details?.publishedFor) {
@ -312,29 +433,206 @@ export default function FormVideoUpdate() {
initState();
}, [refresh, setValue]);
const mapPlacementsToOptions = (placements: string): string[] => {
const mapping: Record<string, string> = {
all: "all",
mabes: "nasional",
polda: "wilayah",
polres: "internasional",
const updateMainCheckboxFromModalLegacy = () => {
const checkedPoldaCount = listDest.filter(
(item) => item.levelNumber === 2 && item.name !== "SATKER POLRI" && checkedLevels.has(item.id)
).length;
const hasSelectedPolda = checkedPoldaCount > 0;
const allPoldaChecked = checkedPoldaCount === listDest.filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI").length;
const checkedSatkerCount = listDest.filter(
(item) => item.levelNumber === 2 && item.name === "SATKER POLRI" && checkedLevels.has(item.id)
).length;
const hasSelectedSatker = checkedSatkerCount > 0;
const allSatkerChecked = checkedSatkerCount === listDest.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI").length;
setUnitSelection(prev => ({
...prev,
polda: hasSelectedPolda,
satker: hasSelectedSatker,
wilayah: hasSelectedPolda || hasSelectedSatker,
}));
};
// Jika placements hanya "all", langsung aktifkan semua checkbox
if (placements.trim() === "all") {
return ["all", "nasional", "wilayah", "internasional"];
const syncModalWithMainCheckbox = () => {
if (mainCheckboxChangeType === "wilayah_checked") {
const poldaIds = listDest
.filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI")
.map(item => item.id);
const satkerIds = listDest
.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI")
.map(item => item.id);
const allSatkerSubIds = listDest
.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI")
.flatMap(item => item.subDestination.map(sub => sub.id));
setCheckedLevels(prev => {
const newSet = new Set(prev);
[...poldaIds, ...satkerIds, ...allSatkerSubIds].forEach(id => newSet.add(id));
return newSet;
});
} else if (mainCheckboxChangeType === "wilayah_unchecked") {
const poldaIds = listDest
.filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI")
.map(item => item.id);
const satkerIds = listDest
.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI")
.map(item => item.id);
const allSatkerSubIds = listDest
.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI")
.flatMap(item => item.subDestination.map(sub => sub.id));
setCheckedLevels(prev => {
const newSet = new Set(prev);
[...poldaIds, ...satkerIds, ...allSatkerSubIds].forEach(id => newSet.delete(id));
return newSet;
});
} else if (mainCheckboxChangeType === "polda_checked") {
const poldaIds = listDest
.filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI")
.map(item => item.id);
setCheckedLevels(prev => {
const newSet = new Set(prev);
poldaIds.forEach(id => newSet.add(id));
return newSet;
});
} else if (mainCheckboxChangeType === "polda_unchecked") {
const poldaIds = listDest
.filter(item => item.levelNumber === 2 && item.name !== "SATKER POLRI")
.map(item => item.id);
setCheckedLevels(prev => {
const newSet = new Set(prev);
poldaIds.forEach(id => newSet.delete(id));
return newSet;
});
} else if (mainCheckboxChangeType === "satker_checked") {
const satkerIds = listDest
.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI")
.map(item => item.id);
const allSatkerSubIds = listDest
.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI")
.flatMap(item => item.subDestination.map(sub => sub.id));
setCheckedLevels(prev => {
const newSet = new Set(prev);
[...satkerIds, ...allSatkerSubIds].forEach(id => newSet.add(id));
return newSet;
});
} else if (mainCheckboxChangeType === "satker_unchecked") {
const satkerIds = listDest
.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI")
.map(item => item.id);
const allSatkerSubIds = listDest
.filter(item => item.levelNumber === 2 && item.name === "SATKER POLRI")
.flatMap(item => item.subDestination.map(sub => sub.id));
setCheckedLevels(prev => {
const newSet = new Set(prev);
[...satkerIds, ...allSatkerSubIds].forEach(id => newSet.delete(id));
return newSet;
});
}
};
const handleFileUnitChange = (fileId: string, key: string, value: boolean) => {
setFileUnitSelections(prev => {
const currentSelection = prev[fileId] || {
semua: false,
nasional: false,
wilayah: false,
international: false,
polda: false,
satker: false,
};
const newSelection = { ...currentSelection, [key]: value };
if (key === "wilayah" && value) {
newSelection.polda = true;
newSelection.satker = true;
// Update fileCheckedLevels for wilayah
setFileCheckedLevels(prevLevels => {
const currentFileLevels = prevLevels[fileId] || new Set<number>();
const newFileLevels = new Set(currentFileLevels);
// Add all POLDA items
listDest.forEach(item => {
if (item.levelNumber === 2 && item.name !== "SATKER POLRI") {
newFileLevels.add(item.id);
}
});
// Add SATKER POLRI items and their sub-destinations
listDest.forEach(item => {
if (item.levelNumber === 2 && item.name === "SATKER POLRI") {
newFileLevels.add(item.id);
item.subDestination.forEach(satkerItem => {
newFileLevels.add(satkerItem.id);
});
}
});
return { ...prevLevels, [fileId]: newFileLevels };
});
} else if (key === "wilayah" && !value) {
newSelection.polda = false;
newSelection.satker = false;
// Clear fileCheckedLevels for wilayah
setFileCheckedLevels(prevLevels => {
const newFileLevels = new Set<number>();
return { ...prevLevels, [fileId]: newFileLevels };
});
} else if (key === "semua") {
newSelection.nasional = value;
newSelection.wilayah = value;
newSelection.international = value;
newSelection.polda = value;
newSelection.satker = value;
}
const options = placements
.split(",")
.map((p) => mapping[p.trim()])
.filter(Boolean);
return { ...prev, [fileId]: newSelection };
});
const allSelected = ["nasional", "wilayah", "internasional"].every((opt) =>
options.includes(opt)
);
// Update filePlacements
setFilePlacements(prev => {
const currentPlacements = prev[fileId] || [];
let newPlacements = [...currentPlacements];
return allSelected ? ["all", ...options] : options;
if (key === "semua" && value) {
newPlacements = ["all", "mabes", "wilayah", "polda", "satker", "international"];
} else if (key === "semua" && !value) {
newPlacements = [];
} else if (key === "nasional" && value) {
if (!newPlacements.includes("mabes")) newPlacements.push("mabes");
} else if (key === "nasional" && !value) {
newPlacements = newPlacements.filter(p => p !== "mabes");
} else if (key === "wilayah" && value) {
if (!newPlacements.includes("wilayah")) newPlacements.push("wilayah");
if (!newPlacements.includes("polda")) newPlacements.push("polda");
if (!newPlacements.includes("satker")) newPlacements.push("satker");
} else if (key === "wilayah" && !value) {
newPlacements = newPlacements.filter(p => !["wilayah", "polda", "satker"].includes(p));
} else if (key === "international" && value) {
if (!newPlacements.includes("international")) newPlacements.push("international");
} else if (key === "international" && !value) {
newPlacements = newPlacements.filter(p => p !== "international");
} else if (key === "polda" && value) {
if (!newPlacements.includes("polda")) newPlacements.push("polda");
} else if (key === "polda" && !value) {
newPlacements = newPlacements.filter(p => p !== "polda");
} else if (key === "satker" && value) {
if (!newPlacements.includes("satker")) newPlacements.push("satker");
} else if (key === "satker" && !value) {
newPlacements = newPlacements.filter(p => p !== "satker");
}
// Remove "all" if any individual option is unchecked
if (newPlacements.includes("all") && !value && key !== "semua") {
newPlacements = newPlacements.filter(p => p !== "all");
}
return { ...prev, [fileId]: newPlacements };
});
};
const handleCheckboxChange = (id: string) => {
@ -354,6 +652,192 @@ export default function FormVideoUpdate() {
}
};
const handleFileCheckboxChangePlacement = (fileId: string, poldaItem: Destination, isChecked: boolean) => {
setFileCheckedLevels(prev => {
const currentFileLevels = prev[fileId] || new Set<number>();
const newFileLevels = new Set(currentFileLevels);
if (isChecked) {
newFileLevels.add(poldaItem.id);
// Add all sub-destinations for SATKER POLRI
if (poldaItem.name === "SATKER POLRI") {
poldaItem.subDestination.forEach((satkerItem: SubDestination) => {
newFileLevels.add(satkerItem.id);
});
}
} else {
newFileLevels.delete(poldaItem.id);
// Remove all sub-destinations for SATKER POLRI
if (poldaItem.name === "SATKER POLRI") {
poldaItem.subDestination.forEach((satkerItem: SubDestination) => {
newFileLevels.delete(satkerItem.id);
});
}
}
return { ...prev, [fileId]: newFileLevels };
});
// Update fileUnitSelections based on checked levels
const updatedFileLevels = fileCheckedLevels[fileId] || new Set<number>();
const hasPolda = listDest.some(item =>
item.levelNumber === 2 &&
item.name !== "SATKER POLRI" &&
updatedFileLevels.has(item.id)
);
const hasSatker = listDest.some(item =>
item.levelNumber === 2 &&
item.name === "SATKER POLRI" &&
updatedFileLevels.has(item.id)
);
setFileUnitSelections(prev => ({
...prev,
[fileId]: {
...prev[fileId],
polda: hasPolda,
satker: hasSatker,
wilayah: hasPolda || hasSatker,
}
}));
};
const updateMainCheckboxFromModal = (fileId: string) => {
const fileLevels = fileCheckedLevels[fileId] || new Set<number>();
const hasPolda = listDest.some(item =>
item.levelNumber === 2 &&
item.name !== "SATKER POLRI" &&
fileLevels.has(item.id)
);
const hasSatker = listDest.some(item =>
item.levelNumber === 2 &&
item.name === "SATKER POLRI" &&
fileLevels.has(item.id)
);
setFileUnitSelections(prev => ({
...prev,
[fileId]: {
...prev[fileId],
polda: hasPolda,
satker: hasSatker,
wilayah: hasPolda || hasSatker,
}
}));
};
const toggleExpand = (poldaId: number) => {
setExpandedPolda(prev => {
const newSet = new Set(prev);
if (newSet.has(poldaId)) {
newSet.delete(poldaId);
} else {
newSet.add(poldaId);
}
return newSet;
});
};
const handleSelectAllSubItems = (fileId: string, poldaItem: Destination) => {
const fileLevels = fileCheckedLevels[fileId] || new Set<number>();
const allSubItemsSelected = poldaItem.subDestination.every(subItem =>
fileLevels.has(subItem.id)
);
setFileCheckedLevels(prev => {
const currentFileLevels = prev[fileId] || new Set<number>();
const newFileLevels = new Set(currentFileLevels);
if (allSubItemsSelected) {
// Unselect all sub-items
poldaItem.subDestination.forEach(subItem => {
newFileLevels.delete(subItem.id);
});
} else {
// Select all sub-items
poldaItem.subDestination.forEach(subItem => {
newFileLevels.add(subItem.id);
});
}
return { ...prev, [fileId]: newFileLevels };
});
};
const getPlacement = (fileId?: string): string => {
if (fileId && filePlacements[fileId]) {
const placements = filePlacements[fileId];
let nowArr = placements.join(",");
nowArr = nowArr?.replaceAll("all", "all");
nowArr = nowArr?.replaceAll("mabes", "mabes");
nowArr = nowArr?.replaceAll("wilayah", "polda");
nowArr = nowArr?.replaceAll("polda", "polda");
nowArr = nowArr?.replaceAll("satker", "satker");
nowArr = nowArr?.replaceAll("international", "international");
return nowArr;
}
return "";
};
const setupPlacement = (fileId: string, placement: string, isChecked: boolean) => {
setFilePlacements(prev => {
const currentPlacements = prev[fileId] || [];
let temp = { ...prev };
if (isChecked) {
if (placement === "all") {
temp[fileId] = ["all", "mabes", "wilayah", "polda", "satker", "international"];
} else if (placement === "wilayah") {
temp[fileId] = [...currentPlacements, "wilayah", "polda", "satker"];
} else if (placement === "polda") {
temp[fileId] = [...currentPlacements, "polda"];
} else if (placement === "satker") {
temp[fileId] = [...currentPlacements, "satker"];
} else {
temp[fileId] = [...currentPlacements, placement as PlacementType];
}
} else {
if (placement === "all") {
temp[fileId] = [];
} else if (placement === "wilayah") {
temp[fileId] = currentPlacements.filter(p => !["wilayah", "polda", "satker"].includes(p));
} else if (placement === "polda") {
temp[fileId] = currentPlacements.filter(p => p !== "polda");
} else if (placement === "satker") {
temp[fileId] = currentPlacements.filter(p => p !== "satker");
} else {
temp[fileId] = currentPlacements.filter(p => p !== placement);
}
}
return temp;
});
};
const updateModalChecklistLevels = (fileId: string) => {
const fileLevels = fileCheckedLevels[fileId] || new Set<number>();
const hasPolda = listDest.some(item =>
item.levelNumber === 2 &&
item.name !== "SATKER POLRI" &&
fileLevels.has(item.id)
);
const hasSatker = listDest.some(item =>
item.levelNumber === 2 &&
item.name === "SATKER POLRI" &&
fileLevels.has(item.id)
);
setFileUnitSelections(prev => ({
...prev,
[fileId]: {
...prev[fileId],
polda: hasPolda,
satker: hasSatker,
wilayah: hasPolda || hasSatker,
}
}));
};
// const save = async (data: VideoSchema) => {
// loading();
// const finalTags = tags.join(", ");
@ -441,6 +925,15 @@ export default function FormVideoUpdate() {
return false;
}
// Update file placements
if (files.length > 0) {
files.forEach((file: any) => {
if (file.id) {
updateFilePlacements(getPlacement(file.id));
}
});
}
if (selectedFiles.length > 0) {
const thumbnail = selectedFiles[0];
const formMedia = new FormData();
@ -638,37 +1131,6 @@ export default function FormVideoUpdate() {
</div>
));
const handleCheckboxChangeImage = (fileId: number, value: string) => {
setSelectedOptions((prev: any) => {
const currentSelections = prev[fileId] || [];
if (value === "all") {
// If "all" is clicked, toggle all options
if (currentSelections.includes("all")) {
return { ...prev, [fileId]: [] }; // Deselect all
}
return {
...prev,
[fileId]: ["all", "nasional", "wilayah", "internasional"],
}; // Select all
} else {
// If any other checkbox is clicked, toggle that checkbox
const updatedSelections = currentSelections.includes(value)
? currentSelections.filter((option: any) => option !== value)
: [...currentSelections, value];
// If all individual options are selected, include "all" automatically
const isAllSelected = ["nasional", "wilayah", "internasional"].every(
(opt) => updatedSelections.includes(opt)
);
return {
...prev,
[fileId]: isAllSelected
? ["all", ...updatedSelections]
: updatedSelections.filter((opt: any) => opt !== "all"),
};
}
});
};
function success() {
MySwal.fire({
@ -885,20 +1347,14 @@ export default function FormVideoUpdate() {
})}
</a>
</div>
<div className="flex flex-wrap gap-3 items-center">
<div>
<Label className="flex items-center space-x-2">
<input
type="checkbox"
checked={selectedOptions[
file.id
]?.includes("all")}
onChange={() =>
handleCheckboxChangeImage(
file.id,
"all"
)
<Checkbox
checked={fileUnitSelections[file.id]?.semua || false}
onCheckedChange={(checked) =>
handleFileUnitChange(file.id, "semua", checked as boolean)
}
className="form-checkbox"
/>
<span>
{t("all", { defaultValue: "All" })}
@ -907,58 +1363,122 @@ export default function FormVideoUpdate() {
</div>
<div>
<Label className="flex items-center space-x-2">
<input
type="checkbox"
checked={selectedOptions[
file.id
]?.includes("nasional")}
onChange={() =>
handleCheckboxChangeImage(
file.id,
"nasional"
)
<Checkbox
checked={fileUnitSelections[file.id]?.nasional || false}
onCheckedChange={(checked) =>
handleFileUnitChange(file.id, "nasional", checked as boolean)
}
className="form-checkbox"
/>
<span>Nasional</span>
</Label>
</div>
<div>
<Label className="flex items-center space-x-2">
<input
type="checkbox"
checked={selectedOptions[
file.id
]?.includes("wilayah")}
onChange={() =>
handleCheckboxChangeImage(
file.id,
"wilayah"
)
<Checkbox
checked={fileUnitSelections[file.id]?.wilayah || false}
onCheckedChange={(checked) =>
handleFileUnitChange(file.id, "wilayah", checked as boolean)
}
className="form-checkbox"
/>
<span>Wilayah</span>
</Label>
</div>
<div>
<Label className="flex items-center space-x-2">
<input
type="checkbox"
checked={selectedOptions[
file.id
]?.includes("internasional")}
onChange={() =>
handleCheckboxChangeImage(
file.id,
"internasional"
)
<Checkbox
checked={fileUnitSelections[file.id]?.international || false}
onCheckedChange={(checked) =>
handleFileUnitChange(file.id, "international", checked as boolean)
}
className="form-checkbox"
/>
<span>Internasional</span>
</Label>
</div>
<div>
<Dialog>
<DialogTrigger asChild>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => setTempFile(file)}
>
Detail Wilayah
</Button>
</DialogTrigger>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Daftar Wilayah POLDA dan SATKER</DialogTitle>
</DialogHeader>
<div className="max-h-96 overflow-y-auto">
{listDest?.filter((item) => item.levelNumber === 2)
.map((poldaItem) => (
<div key={poldaItem.id} className="mb-4">
<div className="flex items-center space-x-2 mb-2">
<Checkbox
checked={fileCheckedLevels[file.id]?.has(poldaItem.id) || false}
onCheckedChange={(checked) =>
handleFileCheckboxChangePlacement(file.id, poldaItem, checked as boolean)
}
/>
<Label className="font-medium">
{poldaItem.name}
</Label>
{poldaItem.name === "SATKER POLRI" && poldaItem.subDestination.length > 0 && (
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => toggleExpand(poldaItem.id)}
>
{expandedPolda.has(poldaItem.id) ? "Tutup" : "Buka"}
</Button>
)}
</div>
{poldaItem.name === "SATKER POLRI" && expandedPolda.has(poldaItem.id) && (
<div className="ml-6 space-y-2">
<div className="flex items-center space-x-2">
<Button
type="button"
variant="outline"
size="sm"
onClick={() => handleSelectAllSubItems(file.id, poldaItem)}
>
Pilih Semua
</Button>
</div>
{poldaItem.subDestination.map((satkerItem) => (
<div key={satkerItem.id} className="flex items-center space-x-2 ml-4">
<Checkbox
checked={fileCheckedLevels[file.id]?.has(satkerItem.id) || false}
onCheckedChange={(checked) => {
setFileCheckedLevels(prev => {
const currentFileLevels = prev[file.id] || new Set<number>();
const newFileLevels = new Set(currentFileLevels);
if (checked) {
newFileLevels.add(satkerItem.id);
} else {
newFileLevels.delete(satkerItem.id);
}
return { ...prev, [file.id]: newFileLevels };
});
updateMainCheckboxFromModal(file.id);
}}
/>
<Label className="text-sm">
{satkerItem.name}
</Label>
</div>
))}
</div>
)}
</div>
))}
</div>
</DialogContent>
</Dialog>
</div>
</div>
</div>
</div>
))}