fix conflict pull main
This commit is contained in:
commit
fdb2a161f6
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
|
|
@ -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>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Reference in New Issue