fix: satker section all and maps
This commit is contained in:
parent
44c6cc6d9d
commit
740d73d689
|
|
@ -115,7 +115,7 @@ const ViewEditor = dynamic(
|
||||||
() => {
|
() => {
|
||||||
return import("@/components/editor/view-editor");
|
return import("@/components/editor/view-editor");
|
||||||
},
|
},
|
||||||
{ ssr: false }
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
interface Destination {
|
interface Destination {
|
||||||
|
|
@ -198,6 +198,12 @@ export default function FormAudioDetail() {
|
||||||
satker: boolean;
|
satker: boolean;
|
||||||
}>
|
}>
|
||||||
>([]);
|
>([]);
|
||||||
|
const [creatorLevelNumber, setCreatorLevelNumber] = useState<number | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
const isContentFromSatker = creatorLevelNumber === 3;
|
||||||
|
const isContentFromMabesOrPolda =
|
||||||
|
creatorLevelNumber === 1 || creatorLevelNumber === 2;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
||||||
|
|
@ -209,7 +215,7 @@ export default function FormAudioDetail() {
|
||||||
const handleFileUnitChange = (
|
const handleFileUnitChange = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
key: keyof typeof unitSelection,
|
key: keyof typeof unitSelection,
|
||||||
value: boolean
|
value: boolean,
|
||||||
) => {
|
) => {
|
||||||
setFileUnitSelections((prev) => {
|
setFileUnitSelections((prev) => {
|
||||||
const newSelections = [...prev];
|
const newSelections = [...prev];
|
||||||
|
|
@ -229,7 +235,7 @@ export default function FormAudioDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[fileIndex] || new Set()
|
newArray[fileIndex] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
@ -260,12 +266,12 @@ export default function FormAudioDetail() {
|
||||||
(item: any) =>
|
(item: any) =>
|
||||||
item.levelNumber === 2 &&
|
item.levelNumber === 2 &&
|
||||||
item.name !== "SATKER POLRI" &&
|
item.name !== "SATKER POLRI" &&
|
||||||
currentFileCheckedLevels.has(Number(item.id))
|
currentFileCheckedLevels.has(Number(item.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!hasSelectedPolda) {
|
if (!hasSelectedPolda) {
|
||||||
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; // Batalkan perubahan
|
||||||
}
|
}
|
||||||
|
|
@ -302,7 +308,7 @@ export default function FormAudioDetail() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (detail?.assignedToTopLevel) {
|
if (detail?.assignedToTopLevel) {
|
||||||
const outputSet = new Set(
|
const outputSet = new Set(
|
||||||
detail.assignedToTopLevel.split(",").map(Number)
|
detail.assignedToTopLevel.split(",").map(Number),
|
||||||
);
|
);
|
||||||
setUnitSelection({
|
setUnitSelection({
|
||||||
semua: outputSet.has(0),
|
semua: outputSet.has(0),
|
||||||
|
|
@ -327,7 +333,7 @@ export default function FormAudioDetail() {
|
||||||
acc[polda.id] = false;
|
acc[polda.id] = false;
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{}
|
{},
|
||||||
);
|
);
|
||||||
setExpandedPolda(initialExpandedState);
|
setExpandedPolda(initialExpandedState);
|
||||||
console.log("polres", initialExpandedState);
|
console.log("polres", initialExpandedState);
|
||||||
|
|
@ -362,7 +368,7 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
const handleUnitChange = (
|
const handleUnitChange = (
|
||||||
key: keyof typeof unitSelection,
|
key: keyof typeof unitSelection,
|
||||||
value: boolean
|
value: boolean,
|
||||||
) => {
|
) => {
|
||||||
if (key === "semua") {
|
if (key === "semua") {
|
||||||
const newState = {
|
const newState = {
|
||||||
|
|
@ -472,7 +478,7 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
const handleCheckboxChange = (id: number) => {
|
const handleCheckboxChange = (id: number) => {
|
||||||
setSelectedPublishers((prev) =>
|
setSelectedPublishers((prev) =>
|
||||||
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
|
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -494,7 +500,7 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
if (scheduleId && scheduleType === "3") {
|
if (scheduleId && scheduleType === "3") {
|
||||||
const findCategory = resCategory.find((o) =>
|
const findCategory = resCategory.find((o) =>
|
||||||
o.name.toLowerCase().includes("pers rilis")
|
o.name.toLowerCase().includes("pers rilis"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (findCategory) {
|
if (findCategory) {
|
||||||
|
|
@ -542,6 +548,9 @@ export default function FormAudioDetail() {
|
||||||
const details = response?.data?.data;
|
const details = response?.data?.data;
|
||||||
setFiles(details?.files);
|
setFiles(details?.files);
|
||||||
setDetail(details);
|
setDetail(details);
|
||||||
|
if (details?.uploadedBy?.userLevel?.levelNumber) {
|
||||||
|
setCreatorLevelNumber(details.uploadedBy.userLevel.levelNumber);
|
||||||
|
}
|
||||||
setMain({
|
setMain({
|
||||||
type: details?.fileType.name,
|
type: details?.fileType.name,
|
||||||
url: details?.files[0]?.url,
|
url: details?.files[0]?.url,
|
||||||
|
|
@ -552,14 +561,14 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
if (details?.assignedToLevel) {
|
if (details?.assignedToLevel) {
|
||||||
const levels = new Set(
|
const levels = new Set(
|
||||||
details.assignedToLevel.split(",").map(Number)
|
details.assignedToLevel.split(",").map(Number),
|
||||||
);
|
);
|
||||||
setCheckedLevels(levels);
|
setCheckedLevels(levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (details?.publishedForObject) {
|
if (details?.publishedForObject) {
|
||||||
const publisherIds = details?.publishedForObject.map(
|
const publisherIds = details?.publishedForObject.map(
|
||||||
(obj: any) => obj.id
|
(obj: any) => obj.id,
|
||||||
);
|
);
|
||||||
setSelectedPublishers(publisherIds);
|
setSelectedPublishers(publisherIds);
|
||||||
}
|
}
|
||||||
|
|
@ -709,7 +718,7 @@ export default function FormAudioDetail() {
|
||||||
const setupPlacement = (
|
const setupPlacement = (
|
||||||
index: number,
|
index: number,
|
||||||
placement: string,
|
placement: string,
|
||||||
checked: boolean
|
checked: boolean,
|
||||||
) => {
|
) => {
|
||||||
let temp = [...filePlacements];
|
let temp = [...filePlacements];
|
||||||
if (checked) {
|
if (checked) {
|
||||||
|
|
@ -720,7 +729,7 @@ export default function FormAudioDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[index] || new Set()
|
newArray[index] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Checklist semua item di modal
|
// Checklist semua item di modal
|
||||||
|
|
@ -770,7 +779,7 @@ export default function FormAudioDetail() {
|
||||||
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
||||||
// JANGAN include satker dalam perhitungan auto "all"
|
// JANGAN include satker dalam perhitungan auto "all"
|
||||||
const nonSatkerItems = now.filter(
|
const nonSatkerItems = now.filter(
|
||||||
(item) => item !== "satker" && item !== "all"
|
(item) => item !== "satker" && item !== "all",
|
||||||
);
|
);
|
||||||
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
||||||
now.push("all");
|
now.push("all");
|
||||||
|
|
@ -785,7 +794,7 @@ export default function FormAudioDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[index] || new Set()
|
newArray[index] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Unchecklist semua item di modal
|
// Unchecklist semua item di modal
|
||||||
|
|
@ -819,7 +828,7 @@ export default function FormAudioDetail() {
|
||||||
// Hapus "all" jika tidak semua item ter-checklist
|
// Hapus "all" jika tidak semua item ter-checklist
|
||||||
if (now.includes("all")) {
|
if (now.includes("all")) {
|
||||||
const nonSatkerItems = now.filter(
|
const nonSatkerItems = now.filter(
|
||||||
(item) => item !== "satker" && item !== "all"
|
(item) => item !== "satker" && item !== "all",
|
||||||
);
|
);
|
||||||
if (nonSatkerItems.length < 3) {
|
if (nonSatkerItems.length < 3) {
|
||||||
const newData = now.filter((b) => b !== "all");
|
const newData = now.filter((b) => b !== "all");
|
||||||
|
|
@ -838,7 +847,7 @@ export default function FormAudioDetail() {
|
||||||
type: string,
|
type: string,
|
||||||
url: string,
|
url: string,
|
||||||
names: string,
|
names: string,
|
||||||
format: string
|
format: string,
|
||||||
) => {
|
) => {
|
||||||
console.log("Test 3 :", type, url, names, format);
|
console.log("Test 3 :", type, url, names, format);
|
||||||
setMain({
|
setMain({
|
||||||
|
|
@ -873,7 +882,7 @@ export default function FormAudioDetail() {
|
||||||
const updateModalChecklistLevels = (
|
const updateModalChecklistLevels = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
placement: string,
|
placement: string,
|
||||||
checked: boolean
|
checked: boolean,
|
||||||
) => {
|
) => {
|
||||||
if (!listDest || listDest.length === 0) return;
|
if (!listDest || listDest.length === 0) return;
|
||||||
|
|
||||||
|
|
@ -906,7 +915,7 @@ export default function FormAudioDetail() {
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Checklist SATKER POLRI dan semua sub-item di bawahnya
|
// Checklist SATKER POLRI dan semua sub-item di bawahnya
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
currentFileLevels.add(Number(satkerItem.id));
|
currentFileLevels.add(Number(satkerItem.id));
|
||||||
|
|
@ -942,7 +951,7 @@ export default function FormAudioDetail() {
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Unchecklist SATKER POLRI dan semua sub-item di bawahnya
|
// Unchecklist SATKER POLRI dan semua sub-item di bawahnya
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
currentFileLevels.delete(Number(satkerItem.id));
|
currentFileLevels.delete(Number(satkerItem.id));
|
||||||
|
|
@ -975,7 +984,7 @@ export default function FormAudioDetail() {
|
||||||
// Fungsi untuk mengupdate checklist levels untuk file tertentu
|
// Fungsi untuk mengupdate checklist levels untuk file tertentu
|
||||||
const handleFileCheckboxChangePlacement = (
|
const handleFileCheckboxChangePlacement = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
levelId: number
|
levelId: number,
|
||||||
) => {
|
) => {
|
||||||
setFileCheckedLevels((prev) => {
|
setFileCheckedLevels((prev) => {
|
||||||
const newArray = [...prev];
|
const newArray = [...prev];
|
||||||
|
|
@ -987,7 +996,7 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
||||||
const poldaItem = listDest.find(
|
const poldaItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (
|
if (
|
||||||
poldaItem &&
|
poldaItem &&
|
||||||
|
|
@ -1010,7 +1019,7 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
||||||
const satkerItem = listDest.find(
|
const satkerItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
||||||
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
||||||
|
|
@ -1041,7 +1050,7 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
// Hitung total POLDA yang ada (bukan SATKER POLRI)
|
// Hitung total POLDA yang ada (bukan SATKER POLRI)
|
||||||
const totalPoldaCount = listDest.filter(
|
const totalPoldaCount = listDest.filter(
|
||||||
(item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI"
|
(item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI",
|
||||||
).length;
|
).length;
|
||||||
|
|
||||||
// Hitung berapa banyak POLDA yang ter-checklist (bukan SATKER POLRI)
|
// Hitung berapa banyak POLDA yang ter-checklist (bukan SATKER POLRI)
|
||||||
|
|
@ -1068,7 +1077,7 @@ export default function FormAudioDetail() {
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
},
|
},
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Hitung berapa banyak POLRES yang ter-checklist
|
// Hitung berapa banyak POLRES yang ter-checklist
|
||||||
|
|
@ -1078,7 +1087,7 @@ export default function FormAudioDetail() {
|
||||||
return (
|
return (
|
||||||
total +
|
total +
|
||||||
item.subDestination.filter((sub: any) =>
|
item.subDestination.filter((sub: any) =>
|
||||||
currentFileLevels.has(Number(sub.id))
|
currentFileLevels.has(Number(sub.id)),
|
||||||
).length
|
).length
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1087,7 +1096,7 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
// Cek apakah SATKER POLRI ter-checklist
|
// Cek apakah SATKER POLRI ter-checklist
|
||||||
const satkerItem = listDest.find(
|
const satkerItem = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
const isSatkerChecked =
|
const isSatkerChecked =
|
||||||
satkerItem && currentFileLevels.has(Number(satkerItem.id));
|
satkerItem && currentFileLevels.has(Number(satkerItem.id));
|
||||||
|
|
@ -1121,7 +1130,7 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
// Cek apakah semua sub-items sudah ter-checklist
|
// Cek apakah semua sub-items sudah ter-checklist
|
||||||
const allSubItemsChecked = polda.subDestination?.every((sub: any) =>
|
const allSubItemsChecked = polda.subDestination?.every((sub: any) =>
|
||||||
currentFileLevels.has(Number(sub.id))
|
currentFileLevels.has(Number(sub.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (allSubItemsChecked) {
|
if (allSubItemsChecked) {
|
||||||
|
|
@ -1204,7 +1213,7 @@ export default function FormAudioDetail() {
|
||||||
{detail &&
|
{detail &&
|
||||||
!categories.find(
|
!categories.find(
|
||||||
(cat) =>
|
(cat) =>
|
||||||
String(cat.id) === String(detail.category.id)
|
String(cat.id) === String(detail.category.id),
|
||||||
) && (
|
) && (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={String(detail.category.id)}
|
key={String(detail.category.id)}
|
||||||
|
|
@ -1464,7 +1473,7 @@ export default function FormAudioDetail() {
|
||||||
Tingkat Distribusi:
|
Tingkat Distribusi:
|
||||||
</p>
|
</p>
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||||
{[
|
{/* {[
|
||||||
{ key: "semua", label: "Semua" },
|
{ key: "semua", label: "Semua" },
|
||||||
{ key: "nasional", label: "Nasional" },
|
{ key: "nasional", label: "Nasional" },
|
||||||
{ key: "wilayah", label: "Wilayah" },
|
{ key: "wilayah", label: "Wilayah" },
|
||||||
|
|
@ -1472,6 +1481,39 @@ export default function FormAudioDetail() {
|
||||||
key: "international",
|
key: "international",
|
||||||
label: "Internasional",
|
label: "Internasional",
|
||||||
},
|
},
|
||||||
|
] */}
|
||||||
|
{[
|
||||||
|
{ key: "semua", label: "Semua" },
|
||||||
|
|
||||||
|
...(isContentFromMabesOrPolda
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
key: "nasional",
|
||||||
|
label: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "international",
|
||||||
|
label: "Internasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "wilayah",
|
||||||
|
label: "Wilayah",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
|
||||||
|
...(isContentFromSatker
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
key: "nasional",
|
||||||
|
label: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "international",
|
||||||
|
label: "Internasional",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
].map((item, idx) => (
|
].map((item, idx) => (
|
||||||
<div
|
<div
|
||||||
key={item.key}
|
key={item.key}
|
||||||
|
|
@ -1488,12 +1530,12 @@ export default function FormAudioDetail() {
|
||||||
handleFileUnitChange(
|
handleFileUnitChange(
|
||||||
index,
|
index,
|
||||||
item.key as keyof typeof unitSelection,
|
item.key as keyof typeof unitSelection,
|
||||||
value as boolean
|
value as boolean,
|
||||||
);
|
);
|
||||||
setupPlacement(
|
setupPlacement(
|
||||||
index,
|
index,
|
||||||
item.key,
|
item.key,
|
||||||
Boolean(value)
|
Boolean(value),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1509,251 +1551,262 @@ export default function FormAudioDetail() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Detail Wilayah */}
|
{/* Detail Wilayah */}
|
||||||
{fileUnitSelections[index]?.wilayah && (
|
{/* {fileUnitSelections[index]?.wilayah && ( */}
|
||||||
<div className="border-t border-gray-200 pt-2">
|
{!isContentFromSatker &&
|
||||||
<p className="text-sm font-medium text-gray-700 mb-2">
|
fileUnitSelections[index]?.wilayah && (
|
||||||
Detail Wilayah:
|
<div className="border-t border-gray-200 pt-2">
|
||||||
</p>
|
<p className="text-sm font-medium text-gray-700 mb-2">
|
||||||
|
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>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -1832,7 +1885,7 @@ export default function FormAudioDetail() {
|
||||||
>
|
>
|
||||||
{template}
|
{template}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1806,7 +1806,7 @@ export default function FormAudio() {
|
||||||
</Card>
|
</Card>
|
||||||
<div className="flex flex-row justify-end gap-3">
|
<div className="flex flex-row justify-end gap-3">
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
{levelNumber !== "2" && levelNumber !== "3" && (
|
{levelNumber !== "2" && (
|
||||||
<Button type="submit" color="primary">
|
<Button type="submit" color="primary">
|
||||||
{t("submit", { defaultValue: "Submit" })}
|
{t("submit", { defaultValue: "Submit" })}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ const ViewEditor = dynamic(
|
||||||
() => {
|
() => {
|
||||||
return import("@/components/editor/view-editor");
|
return import("@/components/editor/view-editor");
|
||||||
},
|
},
|
||||||
{ ssr: false }
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
interface Destination {
|
interface Destination {
|
||||||
|
|
@ -172,6 +172,12 @@ export default function FormImageDetail() {
|
||||||
satker: boolean;
|
satker: boolean;
|
||||||
}>
|
}>
|
||||||
>([]);
|
>([]);
|
||||||
|
const [creatorLevelNumber, setCreatorLevelNumber] = useState<number | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
const isContentFromSatker = creatorLevelNumber === 3;
|
||||||
|
const isContentFromMabesOrPolda =
|
||||||
|
creatorLevelNumber === 1 || creatorLevelNumber === 2;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
||||||
|
|
@ -200,7 +206,7 @@ export default function FormImageDetail() {
|
||||||
const [files, setFiles] = useState<FileType[]>([]);
|
const [files, setFiles] = useState<FileType[]>([]);
|
||||||
const [rejectedFiles, setRejectedFiles] = useState<number[]>([]);
|
const [rejectedFiles, setRejectedFiles] = useState<number[]>([]);
|
||||||
const [expandedPolda, setExpandedPolda] = useState<Record<number, boolean>>(
|
const [expandedPolda, setExpandedPolda] = useState<Record<number, boolean>>(
|
||||||
{}
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
// State untuk melacak apakah perubahan berasal dari checkbox utama
|
// State untuk melacak apakah perubahan berasal dari checkbox utama
|
||||||
|
|
@ -231,7 +237,7 @@ export default function FormImageDetail() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (detail?.assignedToTopLevel) {
|
if (detail?.assignedToTopLevel) {
|
||||||
const outputSet = new Set(
|
const outputSet = new Set(
|
||||||
detail.assignedToTopLevel.split(",").map(Number)
|
detail.assignedToTopLevel.split(",").map(Number),
|
||||||
);
|
);
|
||||||
setUnitSelection({
|
setUnitSelection({
|
||||||
semua: outputSet.has(0),
|
semua: outputSet.has(0),
|
||||||
|
|
@ -260,7 +266,7 @@ export default function FormImageDetail() {
|
||||||
acc[polda.id] = false;
|
acc[polda.id] = false;
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{}
|
{},
|
||||||
);
|
);
|
||||||
setExpandedPolda(initialExpandedState);
|
setExpandedPolda(initialExpandedState);
|
||||||
console.log("polres", initialExpandedState);
|
console.log("polres", initialExpandedState);
|
||||||
|
|
@ -299,7 +305,7 @@ export default function FormImageDetail() {
|
||||||
(item: any) =>
|
(item: any) =>
|
||||||
item.levelNumber === 2 &&
|
item.levelNumber === 2 &&
|
||||||
item.name !== "SATKER POLRI" &&
|
item.name !== "SATKER POLRI" &&
|
||||||
checkedLevels.has(Number(item.id))
|
checkedLevels.has(Number(item.id)),
|
||||||
).length;
|
).length;
|
||||||
|
|
||||||
const checkedPolresCount = listDest.reduce((total: number, item: any) => {
|
const checkedPolresCount = listDest.reduce((total: number, item: any) => {
|
||||||
|
|
@ -308,7 +314,7 @@ export default function FormImageDetail() {
|
||||||
return (
|
return (
|
||||||
total +
|
total +
|
||||||
item.subDestination.filter((sub: any) =>
|
item.subDestination.filter((sub: any) =>
|
||||||
checkedLevels.has(Number(sub.id))
|
checkedLevels.has(Number(sub.id)),
|
||||||
).length
|
).length
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -316,12 +322,12 @@ export default function FormImageDetail() {
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
const checkedSatkerCount = satkerItem
|
const checkedSatkerCount = satkerItem
|
||||||
? (checkedLevels.has(Number(satkerItem.id)) ? 1 : 0) +
|
? (checkedLevels.has(Number(satkerItem.id)) ? 1 : 0) +
|
||||||
(satkerItem.subDestination?.filter((sub: any) =>
|
(satkerItem.subDestination?.filter((sub: any) =>
|
||||||
checkedLevels.has(Number(sub.id))
|
checkedLevels.has(Number(sub.id)),
|
||||||
).length || 0)
|
).length || 0)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
|
@ -391,7 +397,7 @@ export default function FormImageDetail() {
|
||||||
} else if (mainCheckboxChangeType === "satker_checked") {
|
} else if (mainCheckboxChangeType === "satker_checked") {
|
||||||
// Checklist satker
|
// Checklist satker
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
newCheckedLevels.add(Number(satkerItem.id));
|
newCheckedLevels.add(Number(satkerItem.id));
|
||||||
|
|
@ -439,7 +445,7 @@ export default function FormImageDetail() {
|
||||||
} else if (mainCheckboxChangeType === "satker_unchecked") {
|
} else if (mainCheckboxChangeType === "satker_unchecked") {
|
||||||
// Clear satker dan semua sub-item di bawahnya dari checkedLevels
|
// Clear satker dan semua sub-item di bawahnya dari checkedLevels
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
newCheckedLevels.delete(Number(satkerItem.id));
|
newCheckedLevels.delete(Number(satkerItem.id));
|
||||||
|
|
@ -466,7 +472,7 @@ export default function FormImageDetail() {
|
||||||
const handleFileUnitChange = (
|
const handleFileUnitChange = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
key: keyof typeof unitSelection,
|
key: keyof typeof unitSelection,
|
||||||
value: boolean
|
value: boolean,
|
||||||
) => {
|
) => {
|
||||||
setFileUnitSelections((prev) => {
|
setFileUnitSelections((prev) => {
|
||||||
const newSelections = [...prev];
|
const newSelections = [...prev];
|
||||||
|
|
@ -486,7 +492,7 @@ export default function FormImageDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[fileIndex] || new Set()
|
newArray[fileIndex] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
@ -517,12 +523,12 @@ export default function FormImageDetail() {
|
||||||
(item: any) =>
|
(item: any) =>
|
||||||
item.levelNumber === 2 &&
|
item.levelNumber === 2 &&
|
||||||
item.name !== "SATKER POLRI" &&
|
item.name !== "SATKER POLRI" &&
|
||||||
currentFileCheckedLevels.has(Number(item.id))
|
currentFileCheckedLevels.has(Number(item.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!hasSelectedPolda) {
|
if (!hasSelectedPolda) {
|
||||||
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; // Batalkan perubahan
|
||||||
}
|
}
|
||||||
|
|
@ -552,7 +558,7 @@ export default function FormImageDetail() {
|
||||||
// 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,
|
||||||
value: boolean
|
value: boolean,
|
||||||
) => {
|
) => {
|
||||||
// Set flag bahwa perubahan berasal dari checkbox utama
|
// Set flag bahwa perubahan berasal dari checkbox utama
|
||||||
setIsUpdatingFromMainCheckbox(true);
|
setIsUpdatingFromMainCheckbox(true);
|
||||||
|
|
@ -578,13 +584,13 @@ export default function FormImageDetail() {
|
||||||
(item: any) =>
|
(item: any) =>
|
||||||
item.levelNumber === 2 &&
|
item.levelNumber === 2 &&
|
||||||
item.name !== "SATKER POLRI" &&
|
item.name !== "SATKER POLRI" &&
|
||||||
checkedLevels.has(Number(item.id))
|
checkedLevels.has(Number(item.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!hasSelectedPolda) {
|
if (!hasSelectedPolda) {
|
||||||
// Jika tidak ada POLDA yang dipilih, tampilkan peringatan dan batalkan
|
// Jika tidak ada POLDA yang dipilih, tampilkan peringatan dan batalkan
|
||||||
alert(
|
alert(
|
||||||
"Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES."
|
"Harap pilih POLDA di Modal terlebih dahulu sebelum mengaktifkan checkbox POLRES.",
|
||||||
);
|
);
|
||||||
// Reset flag karena perubahan dibatalkan
|
// Reset flag karena perubahan dibatalkan
|
||||||
setIsUpdatingFromMainCheckbox(false);
|
setIsUpdatingFromMainCheckbox(false);
|
||||||
|
|
@ -640,14 +646,14 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
const handleCheckboxChange = (id: number) => {
|
const handleCheckboxChange = (id: number) => {
|
||||||
setSelectedPublishers((prev) =>
|
setSelectedPublishers((prev) =>
|
||||||
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
|
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fungsi untuk mengupdate checklist levels untuk file tertentu
|
// Fungsi untuk mengupdate checklist levels untuk file tertentu
|
||||||
const handleFileCheckboxChangePlacement = (
|
const handleFileCheckboxChangePlacement = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
levelId: number
|
levelId: number,
|
||||||
) => {
|
) => {
|
||||||
setFileCheckedLevels((prev) => {
|
setFileCheckedLevels((prev) => {
|
||||||
const newArray = [...prev];
|
const newArray = [...prev];
|
||||||
|
|
@ -659,7 +665,7 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
||||||
const poldaItem = listDest.find(
|
const poldaItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (
|
if (
|
||||||
poldaItem &&
|
poldaItem &&
|
||||||
|
|
@ -682,7 +688,7 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
||||||
const satkerItem = listDest.find(
|
const satkerItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
||||||
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
||||||
|
|
@ -710,7 +716,7 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
// Cek apakah semua sub-items sudah ter-checklist
|
// Cek apakah semua sub-items sudah ter-checklist
|
||||||
const allSubItemsChecked = polda.subDestination?.every((sub: any) =>
|
const allSubItemsChecked = polda.subDestination?.every((sub: any) =>
|
||||||
currentFileLevels.has(Number(sub.id))
|
currentFileLevels.has(Number(sub.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (allSubItemsChecked) {
|
if (allSubItemsChecked) {
|
||||||
|
|
@ -750,7 +756,7 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
// Hitung total POLDA yang ada (bukan SATKER POLRI)
|
// Hitung total POLDA yang ada (bukan SATKER POLRI)
|
||||||
const totalPoldaCount = listDest.filter(
|
const totalPoldaCount = listDest.filter(
|
||||||
(item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI"
|
(item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI",
|
||||||
).length;
|
).length;
|
||||||
|
|
||||||
// Hitung berapa banyak POLDA yang ter-checklist (bukan SATKER POLRI)
|
// Hitung berapa banyak POLDA yang ter-checklist (bukan SATKER POLRI)
|
||||||
|
|
@ -777,7 +783,7 @@ export default function FormImageDetail() {
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
},
|
},
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Hitung berapa banyak POLRES yang ter-checklist
|
// Hitung berapa banyak POLRES yang ter-checklist
|
||||||
|
|
@ -787,7 +793,7 @@ export default function FormImageDetail() {
|
||||||
return (
|
return (
|
||||||
total +
|
total +
|
||||||
item.subDestination.filter((sub: any) =>
|
item.subDestination.filter((sub: any) =>
|
||||||
currentFileLevels.has(Number(sub.id))
|
currentFileLevels.has(Number(sub.id)),
|
||||||
).length
|
).length
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -796,7 +802,7 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
// Cek apakah SATKER POLRI ter-checklist
|
// Cek apakah SATKER POLRI ter-checklist
|
||||||
const satkerItem = listDest.find(
|
const satkerItem = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
const isSatkerChecked =
|
const isSatkerChecked =
|
||||||
satkerItem && currentFileLevels.has(Number(satkerItem.id));
|
satkerItem && currentFileLevels.has(Number(satkerItem.id));
|
||||||
|
|
@ -833,7 +839,7 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
||||||
const poldaItem = listDest.find(
|
const poldaItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (
|
if (
|
||||||
poldaItem &&
|
poldaItem &&
|
||||||
|
|
@ -856,7 +862,7 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
||||||
const satkerItem = listDest.find(
|
const satkerItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
||||||
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
||||||
|
|
@ -887,7 +893,7 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
if (scheduleId && scheduleType === "3") {
|
if (scheduleId && scheduleType === "3") {
|
||||||
const findCategory = resCategory.find((o) =>
|
const findCategory = resCategory.find((o) =>
|
||||||
o.name.toLowerCase().includes("pers rilis")
|
o.name.toLowerCase().includes("pers rilis"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (findCategory) {
|
if (findCategory) {
|
||||||
|
|
@ -936,6 +942,11 @@ export default function FormImageDetail() {
|
||||||
console.log("detail", details);
|
console.log("detail", details);
|
||||||
setFiles(details?.files);
|
setFiles(details?.files);
|
||||||
setDetail(details);
|
setDetail(details);
|
||||||
|
|
||||||
|
if (details?.uploadedBy?.userLevel?.levelNumber) {
|
||||||
|
setCreatorLevelNumber(details.uploadedBy.userLevel.levelNumber);
|
||||||
|
}
|
||||||
|
|
||||||
setMain({
|
setMain({
|
||||||
type: details?.fileType.name,
|
type: details?.fileType.name,
|
||||||
url: details?.files[0]?.url,
|
url: details?.files[0]?.url,
|
||||||
|
|
@ -946,14 +957,14 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
if (details?.assignedToLevel) {
|
if (details?.assignedToLevel) {
|
||||||
const levels = new Set<number>(
|
const levels = new Set<number>(
|
||||||
details.assignedToLevel.split(",").map(Number)
|
details.assignedToLevel.split(",").map(Number),
|
||||||
);
|
);
|
||||||
setCheckedLevels(levels);
|
setCheckedLevels(levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (details?.publishedForObject) {
|
if (details?.publishedForObject) {
|
||||||
const publisherIds = details?.publishedForObject?.map(
|
const publisherIds = details?.publishedForObject?.map(
|
||||||
(obj: any) => obj.id
|
(obj: any) => obj.id,
|
||||||
);
|
);
|
||||||
setSelectedPublishers(publisherIds);
|
setSelectedPublishers(publisherIds);
|
||||||
}
|
}
|
||||||
|
|
@ -963,7 +974,7 @@ export default function FormImageDetail() {
|
||||||
|
|
||||||
const filesData = details.files || [];
|
const filesData = details.files || [];
|
||||||
const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) =>
|
const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) =>
|
||||||
file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg"
|
file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg",
|
||||||
);
|
);
|
||||||
setDetailThumb(fileUrls);
|
setDetailThumb(fileUrls);
|
||||||
|
|
||||||
|
|
@ -1083,7 +1094,7 @@ export default function FormImageDetail() {
|
||||||
const setupPlacement = (
|
const setupPlacement = (
|
||||||
index: number,
|
index: number,
|
||||||
placement: string,
|
placement: string,
|
||||||
checked: boolean
|
checked: boolean,
|
||||||
) => {
|
) => {
|
||||||
let temp = [...filePlacements];
|
let temp = [...filePlacements];
|
||||||
if (checked) {
|
if (checked) {
|
||||||
|
|
@ -1094,7 +1105,7 @@ export default function FormImageDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[index] || new Set()
|
newArray[index] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Checklist semua item di modal
|
// Checklist semua item di modal
|
||||||
|
|
@ -1144,7 +1155,7 @@ export default function FormImageDetail() {
|
||||||
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
||||||
// JANGAN include satker dalam perhitungan auto "all"
|
// JANGAN include satker dalam perhitungan auto "all"
|
||||||
const nonSatkerItems = now.filter(
|
const nonSatkerItems = now.filter(
|
||||||
(item) => item !== "satker" && item !== "all"
|
(item) => item !== "satker" && item !== "all",
|
||||||
);
|
);
|
||||||
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
||||||
now.push("all");
|
now.push("all");
|
||||||
|
|
@ -1159,7 +1170,7 @@ export default function FormImageDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[index] || new Set()
|
newArray[index] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Unchecklist semua item di modal
|
// Unchecklist semua item di modal
|
||||||
|
|
@ -1193,7 +1204,7 @@ export default function FormImageDetail() {
|
||||||
// Hapus "all" jika tidak semua item ter-checklist
|
// Hapus "all" jika tidak semua item ter-checklist
|
||||||
if (now.includes("all")) {
|
if (now.includes("all")) {
|
||||||
const nonSatkerItems = now.filter(
|
const nonSatkerItems = now.filter(
|
||||||
(item) => item !== "satker" && item !== "all"
|
(item) => item !== "satker" && item !== "all",
|
||||||
);
|
);
|
||||||
if (nonSatkerItems.length < 3) {
|
if (nonSatkerItems.length < 3) {
|
||||||
const newData = now.filter((b) => b !== "all");
|
const newData = now.filter((b) => b !== "all");
|
||||||
|
|
@ -1212,7 +1223,7 @@ export default function FormImageDetail() {
|
||||||
const updateModalChecklistLevels = (
|
const updateModalChecklistLevels = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
placement: string,
|
placement: string,
|
||||||
checked: boolean
|
checked: boolean,
|
||||||
) => {
|
) => {
|
||||||
if (!listDest || listDest.length === 0) return;
|
if (!listDest || listDest.length === 0) return;
|
||||||
|
|
||||||
|
|
@ -1245,7 +1256,7 @@ export default function FormImageDetail() {
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Checklist SATKER POLRI dan semua sub-item di bawahnya
|
// Checklist SATKER POLRI dan semua sub-item di bawahnya
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
currentFileLevels.add(Number(satkerItem.id));
|
currentFileLevels.add(Number(satkerItem.id));
|
||||||
|
|
@ -1281,7 +1292,7 @@ export default function FormImageDetail() {
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Unchecklist SATKER POLRI dan semua sub-item di bawahnya
|
// Unchecklist SATKER POLRI dan semua sub-item di bawahnya
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
currentFileLevels.delete(Number(satkerItem.id));
|
currentFileLevels.delete(Number(satkerItem.id));
|
||||||
|
|
@ -1311,7 +1322,7 @@ export default function FormImageDetail() {
|
||||||
type: string,
|
type: string,
|
||||||
url: string,
|
url: string,
|
||||||
names: string,
|
names: string,
|
||||||
format: string
|
format: string,
|
||||||
) => {
|
) => {
|
||||||
console.log("Test 3 :", type, url, names, format);
|
console.log("Test 3 :", type, url, names, format);
|
||||||
setMain({
|
setMain({
|
||||||
|
|
@ -1411,7 +1422,7 @@ export default function FormImageDetail() {
|
||||||
{detail &&
|
{detail &&
|
||||||
!categories.find(
|
!categories.find(
|
||||||
(cat) =>
|
(cat) =>
|
||||||
String(cat.id) === String(detail.category.id)
|
String(cat.id) === String(detail.category.id),
|
||||||
) && (
|
) && (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={String(detail.category.id)}
|
key={String(detail.category.id)}
|
||||||
|
|
@ -1732,7 +1743,7 @@ export default function FormImageDetail() {
|
||||||
Tingkat Distribusi:
|
Tingkat Distribusi:
|
||||||
</p>
|
</p>
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||||
{[
|
{/* {[
|
||||||
{ key: "semua", label: "Semua" },
|
{ key: "semua", label: "Semua" },
|
||||||
{ key: "nasional", label: "Nasional" },
|
{ key: "nasional", label: "Nasional" },
|
||||||
{ key: "wilayah", label: "Wilayah" },
|
{ key: "wilayah", label: "Wilayah" },
|
||||||
|
|
@ -1740,6 +1751,39 @@ export default function FormImageDetail() {
|
||||||
key: "international",
|
key: "international",
|
||||||
label: "Internasional",
|
label: "Internasional",
|
||||||
},
|
},
|
||||||
|
] */}
|
||||||
|
{[
|
||||||
|
{ key: "semua", label: "Semua" },
|
||||||
|
|
||||||
|
...(isContentFromMabesOrPolda
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
key: "nasional",
|
||||||
|
label: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "international",
|
||||||
|
label: "Internasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "wilayah",
|
||||||
|
label: "Wilayah",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
|
||||||
|
...(isContentFromSatker
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
key: "nasional",
|
||||||
|
label: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "international",
|
||||||
|
label: "Internasional",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
].map((item, idx) => (
|
].map((item, idx) => (
|
||||||
<div
|
<div
|
||||||
key={item.key}
|
key={item.key}
|
||||||
|
|
@ -1756,12 +1800,12 @@ export default function FormImageDetail() {
|
||||||
handleFileUnitChange(
|
handleFileUnitChange(
|
||||||
index,
|
index,
|
||||||
item.key as keyof typeof unitSelection,
|
item.key as keyof typeof unitSelection,
|
||||||
value as boolean
|
value as boolean,
|
||||||
);
|
);
|
||||||
setupPlacement(
|
setupPlacement(
|
||||||
index,
|
index,
|
||||||
item.key,
|
item.key,
|
||||||
Boolean(value)
|
Boolean(value),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1777,246 +1821,257 @@ export default function FormImageDetail() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Detail Wilayah */}
|
{/* Detail Wilayah */}
|
||||||
{fileUnitSelections[index]?.wilayah && (
|
{/* {fileUnitSelections[index]?.wilayah && ( */}
|
||||||
<div className="border-t border-gray-200 pt-2">
|
{!isContentFromSatker &&
|
||||||
<p className="text-sm font-medium text-gray-700 mb-2">
|
fileUnitSelections[index]?.wilayah && (
|
||||||
Detail Wilayah:
|
<div className="border-t border-gray-200 pt-2">
|
||||||
</p>
|
<p className="text-sm font-medium text-gray-700 mb-2">
|
||||||
|
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>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -2095,7 +2150,7 @@ export default function FormImageDetail() {
|
||||||
>
|
>
|
||||||
{template}
|
{template}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ const CustomEditor = dynamic(
|
||||||
() => {
|
() => {
|
||||||
return import("@/components/editor/custom-editor");
|
return import("@/components/editor/custom-editor");
|
||||||
},
|
},
|
||||||
{ ssr: false }
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function FormImage() {
|
export default function FormImage() {
|
||||||
|
|
@ -117,7 +117,7 @@ export default function FormImage() {
|
||||||
const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
|
const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
|
||||||
const [articleBody, setArticleBody] = useState<string>("");
|
const [articleBody, setArticleBody] = useState<string>("");
|
||||||
const [selectedArticleId, setSelectedArticleId] = useState<string | null>(
|
const [selectedArticleId, setSelectedArticleId] = useState<string | null>(
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
||||||
const [selectedWritingStyle, setSelectedWritingStyle] =
|
const [selectedWritingStyle, setSelectedWritingStyle] =
|
||||||
|
|
@ -183,17 +183,17 @@ export default function FormImage() {
|
||||||
.filter(
|
.filter(
|
||||||
(file) =>
|
(file) =>
|
||||||
["image/jpeg", "image/png", "image/jpg"].includes(file.type) &&
|
["image/jpeg", "image/png", "image/jpg"].includes(file.type) &&
|
||||||
file.size <= MAX_FILE_SIZE
|
file.size <= MAX_FILE_SIZE,
|
||||||
)
|
)
|
||||||
.map((file) =>
|
.map((file) =>
|
||||||
Object.assign(file, {
|
Object.assign(file, {
|
||||||
preview: URL.createObjectURL(file),
|
preview: URL.createObjectURL(file),
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (validFiles.length === 0) {
|
if (validFiles.length === 0) {
|
||||||
toast.error(
|
toast.error(
|
||||||
"File tidak valid. Hanya .jpg, .jpeg, .png maksimal 100MB yang diperbolehkan."
|
"File tidak valid. Hanya .jpg, .jpeg, .png maksimal 100MB yang diperbolehkan.",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -227,12 +227,12 @@ export default function FormImage() {
|
||||||
files.every(
|
files.every(
|
||||||
(file: File) =>
|
(file: File) =>
|
||||||
["image/jpeg", "image/png", "image/jpg"].includes(file.type) &&
|
["image/jpeg", "image/png", "image/jpg"].includes(file.type) &&
|
||||||
file.size <= 100 * 1024 * 1024
|
file.size <= 100 * 1024 * 1024,
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
message:
|
message:
|
||||||
"Hanya file .jpg, .jpeg, .png, maksimal 100MB yang diperbolehkan.",
|
"Hanya file .jpg, .jpeg, .png, maksimal 100MB yang diperbolehkan.",
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
categoryId: z.string().min(1, { message: "Kategori wajib dipilih." }),
|
categoryId: z.string().min(1, { message: "Kategori wajib dipilih." }),
|
||||||
tags: z
|
tags: z
|
||||||
|
|
@ -454,7 +454,7 @@ export default function FormImage() {
|
||||||
const articleData = await waitForStatusUpdate();
|
const articleData = await waitForStatusUpdate();
|
||||||
const cleanArticleBody = articleData?.articleBody?.replace(
|
const cleanArticleBody = articleData?.articleBody?.replace(
|
||||||
/<img[^>]*>/g,
|
/<img[^>]*>/g,
|
||||||
""
|
"",
|
||||||
);
|
);
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
setArticleBody(cleanArticleBody || "");
|
setArticleBody(cleanArticleBody || "");
|
||||||
|
|
@ -507,7 +507,7 @@ export default function FormImage() {
|
||||||
|
|
||||||
if (scheduleId && scheduleType === "3") {
|
if (scheduleId && scheduleType === "3") {
|
||||||
const findCategory = resCategory.find((o) =>
|
const findCategory = resCategory.find((o) =>
|
||||||
o.name.toLowerCase().includes("pers rilis")
|
o.name.toLowerCase().includes("pers rilis"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (findCategory) {
|
if (findCategory) {
|
||||||
|
|
@ -530,7 +530,7 @@ export default function FormImage() {
|
||||||
setPublishedFor(
|
setPublishedFor(
|
||||||
options
|
options
|
||||||
.filter((opt: any) => opt.id !== "all")
|
.filter((opt: any) => opt.id !== "all")
|
||||||
.map((opt: any) => opt.id)
|
.map((opt: any) => opt.id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -594,11 +594,16 @@ export default function FormImage() {
|
||||||
} else if (data.rewriteDescription && selectedFileType === "rewrite") {
|
} else if (data.rewriteDescription && selectedFileType === "rewrite") {
|
||||||
finalDescription = data.rewriteDescription;
|
finalDescription = data.rewriteDescription;
|
||||||
console.log("📤 Upload versi rewrite");
|
console.log("📤 Upload versi rewrite");
|
||||||
} else {
|
} else if (data.description?.trim()) {
|
||||||
// fallback: gunakan versi Indonesia original
|
finalDescription = data.description;
|
||||||
finalDescription = data.descriptionOri ?? "";
|
} else if (data.descriptionOri?.trim()) {
|
||||||
console.log("📤 Upload versi Indonesia (original)");
|
finalDescription = data.descriptionOri;
|
||||||
}
|
}
|
||||||
|
// else {
|
||||||
|
// // fallback: gunakan versi Indonesia original
|
||||||
|
// finalDescription = data.descriptionOri ?? "";
|
||||||
|
// console.log("📤 Upload versi Indonesia (original)");
|
||||||
|
// }
|
||||||
|
|
||||||
if (!finalDescription?.trim()) {
|
if (!finalDescription?.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
|
|
@ -690,7 +695,7 @@ export default function FormImage() {
|
||||||
index,
|
index,
|
||||||
String(id),
|
String(id),
|
||||||
item,
|
item,
|
||||||
fileTypeId == "2" || fileTypeId == "4" ? item.duration : "0"
|
fileTypeId == "2" || fileTypeId == "4" ? item.duration : "0",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -717,7 +722,7 @@ export default function FormImage() {
|
||||||
idx: number,
|
idx: number,
|
||||||
id: string,
|
id: string,
|
||||||
file: any,
|
file: any,
|
||||||
duration: string
|
duration: string,
|
||||||
) {
|
) {
|
||||||
console.log(idx, id, file, duration);
|
console.log(idx, id, file, duration);
|
||||||
|
|
||||||
|
|
@ -753,7 +758,7 @@ export default function FormImage() {
|
||||||
onChunkComplete: (
|
onChunkComplete: (
|
||||||
chunkSize: any,
|
chunkSize: any,
|
||||||
bytesAccepted: any,
|
bytesAccepted: any,
|
||||||
bytesTotal: any
|
bytesTotal: any,
|
||||||
) => {
|
) => {
|
||||||
const uploadPersen = Math.floor((bytesAccepted / bytesTotal) * 100);
|
const uploadPersen = Math.floor((bytesAccepted / bytesTotal) * 100);
|
||||||
progressInfo[idx].percentage = uploadPersen;
|
progressInfo[idx].percentage = uploadPersen;
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ const ViewEditor = dynamic(
|
||||||
() => {
|
() => {
|
||||||
return import("@/components/editor/view-editor");
|
return import("@/components/editor/view-editor");
|
||||||
},
|
},
|
||||||
{ ssr: false }
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
interface Destination {
|
interface Destination {
|
||||||
|
|
@ -191,6 +191,12 @@ export default function FormTeksDetail() {
|
||||||
satker: boolean;
|
satker: boolean;
|
||||||
}>
|
}>
|
||||||
>([]);
|
>([]);
|
||||||
|
const [creatorLevelNumber, setCreatorLevelNumber] = useState<number | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
const isContentFromSatker = creatorLevelNumber === 3;
|
||||||
|
const isContentFromMabesOrPolda =
|
||||||
|
creatorLevelNumber === 1 || creatorLevelNumber === 2;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
||||||
|
|
@ -202,7 +208,7 @@ export default function FormTeksDetail() {
|
||||||
const handleFileUnitChange = (
|
const handleFileUnitChange = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
key: keyof typeof unitSelection,
|
key: keyof typeof unitSelection,
|
||||||
value: boolean
|
value: boolean,
|
||||||
) => {
|
) => {
|
||||||
setFileUnitSelections((prev) => {
|
setFileUnitSelections((prev) => {
|
||||||
const newSelections = [...prev];
|
const newSelections = [...prev];
|
||||||
|
|
@ -222,7 +228,7 @@ export default function FormTeksDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[fileIndex] || new Set()
|
newArray[fileIndex] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
@ -253,12 +259,12 @@ export default function FormTeksDetail() {
|
||||||
(item: any) =>
|
(item: any) =>
|
||||||
item.levelNumber === 2 &&
|
item.levelNumber === 2 &&
|
||||||
item.name !== "SATKER POLRI" &&
|
item.name !== "SATKER POLRI" &&
|
||||||
currentFileCheckedLevels.has(Number(item.id))
|
currentFileCheckedLevels.has(Number(item.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!hasSelectedPolda) {
|
if (!hasSelectedPolda) {
|
||||||
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; // Batalkan perubahan
|
||||||
}
|
}
|
||||||
|
|
@ -297,7 +303,7 @@ export default function FormTeksDetail() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (detail?.assignedToTopLevel) {
|
if (detail?.assignedToTopLevel) {
|
||||||
const outputSet = new Set(
|
const outputSet = new Set(
|
||||||
detail.assignedToTopLevel.split(",").map(Number)
|
detail.assignedToTopLevel.split(",").map(Number),
|
||||||
);
|
);
|
||||||
setUnitSelection({
|
setUnitSelection({
|
||||||
semua: outputSet.has(0),
|
semua: outputSet.has(0),
|
||||||
|
|
@ -322,7 +328,7 @@ export default function FormTeksDetail() {
|
||||||
acc[polda.id] = false;
|
acc[polda.id] = false;
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{}
|
{},
|
||||||
);
|
);
|
||||||
setExpandedPolda(initialExpandedState);
|
setExpandedPolda(initialExpandedState);
|
||||||
console.log("polres", initialExpandedState);
|
console.log("polres", initialExpandedState);
|
||||||
|
|
@ -357,7 +363,7 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
const handleUnitChange = (
|
const handleUnitChange = (
|
||||||
key: keyof typeof unitSelection,
|
key: keyof typeof unitSelection,
|
||||||
value: boolean
|
value: boolean,
|
||||||
) => {
|
) => {
|
||||||
if (key === "semua") {
|
if (key === "semua") {
|
||||||
const newState = {
|
const newState = {
|
||||||
|
|
@ -436,7 +442,7 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
const handleCheckboxChange = (id: number) => {
|
const handleCheckboxChange = (id: number) => {
|
||||||
setSelectedPublishers((prev) =>
|
setSelectedPublishers((prev) =>
|
||||||
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
|
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -458,7 +464,7 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
if (scheduleId && scheduleType === "3") {
|
if (scheduleId && scheduleType === "3") {
|
||||||
const findCategory = resCategory.find((o) =>
|
const findCategory = resCategory.find((o) =>
|
||||||
o.name.toLowerCase().includes("pers rilis")
|
o.name.toLowerCase().includes("pers rilis"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (findCategory) {
|
if (findCategory) {
|
||||||
|
|
@ -507,6 +513,9 @@ export default function FormTeksDetail() {
|
||||||
console.log("detail", details);
|
console.log("detail", details);
|
||||||
setFiles(details?.files);
|
setFiles(details?.files);
|
||||||
setDetail(details);
|
setDetail(details);
|
||||||
|
if (details?.uploadedBy?.userLevel?.levelNumber) {
|
||||||
|
setCreatorLevelNumber(details.uploadedBy.userLevel.levelNumber);
|
||||||
|
}
|
||||||
setMain({
|
setMain({
|
||||||
type: details?.fileType.name,
|
type: details?.fileType.name,
|
||||||
url: details?.files[0]?.url,
|
url: details?.files[0]?.url,
|
||||||
|
|
@ -517,14 +526,14 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
if (details?.assignedToLevel) {
|
if (details?.assignedToLevel) {
|
||||||
const levels = new Set(
|
const levels = new Set(
|
||||||
details.assignedToLevel.split(",").map(Number)
|
details.assignedToLevel.split(",").map(Number),
|
||||||
);
|
);
|
||||||
setCheckedLevels(levels);
|
setCheckedLevels(levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (details?.publishedForObject) {
|
if (details?.publishedForObject) {
|
||||||
const publisherIds = details?.publishedForObject?.map(
|
const publisherIds = details?.publishedForObject?.map(
|
||||||
(obj: any) => obj.id
|
(obj: any) => obj.id,
|
||||||
);
|
);
|
||||||
setSelectedPublishers(publisherIds);
|
setSelectedPublishers(publisherIds);
|
||||||
}
|
}
|
||||||
|
|
@ -696,7 +705,7 @@ export default function FormTeksDetail() {
|
||||||
type: string,
|
type: string,
|
||||||
url: string,
|
url: string,
|
||||||
names: string,
|
names: string,
|
||||||
format: string
|
format: string,
|
||||||
) => {
|
) => {
|
||||||
console.log("Test 3 :", type, url, names, format);
|
console.log("Test 3 :", type, url, names, format);
|
||||||
setMain({
|
setMain({
|
||||||
|
|
@ -723,7 +732,7 @@ export default function FormTeksDetail() {
|
||||||
const setupPlacement = (
|
const setupPlacement = (
|
||||||
index: number,
|
index: number,
|
||||||
placement: string,
|
placement: string,
|
||||||
checked: boolean
|
checked: boolean,
|
||||||
) => {
|
) => {
|
||||||
let temp = [...filePlacements];
|
let temp = [...filePlacements];
|
||||||
if (checked) {
|
if (checked) {
|
||||||
|
|
@ -734,7 +743,7 @@ export default function FormTeksDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[index] || new Set()
|
newArray[index] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Checklist semua item di modal
|
// Checklist semua item di modal
|
||||||
|
|
@ -784,7 +793,7 @@ export default function FormTeksDetail() {
|
||||||
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
||||||
// JANGAN include satker dalam perhitungan auto "all"
|
// JANGAN include satker dalam perhitungan auto "all"
|
||||||
const nonSatkerItems = now.filter(
|
const nonSatkerItems = now.filter(
|
||||||
(item) => item !== "satker" && item !== "all"
|
(item) => item !== "satker" && item !== "all",
|
||||||
);
|
);
|
||||||
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
||||||
now.push("all");
|
now.push("all");
|
||||||
|
|
@ -799,7 +808,7 @@ export default function FormTeksDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[index] || new Set()
|
newArray[index] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Unchecklist semua item di modal
|
// Unchecklist semua item di modal
|
||||||
|
|
@ -833,7 +842,7 @@ export default function FormTeksDetail() {
|
||||||
// Hapus "all" jika tidak semua item ter-checklist
|
// Hapus "all" jika tidak semua item ter-checklist
|
||||||
if (now.includes("all")) {
|
if (now.includes("all")) {
|
||||||
const nonSatkerItems = now.filter(
|
const nonSatkerItems = now.filter(
|
||||||
(item) => item !== "satker" && item !== "all"
|
(item) => item !== "satker" && item !== "all",
|
||||||
);
|
);
|
||||||
if (nonSatkerItems.length < 3) {
|
if (nonSatkerItems.length < 3) {
|
||||||
const newData = now.filter((b) => b !== "all");
|
const newData = now.filter((b) => b !== "all");
|
||||||
|
|
@ -851,7 +860,7 @@ export default function FormTeksDetail() {
|
||||||
const updateModalChecklistLevels = (
|
const updateModalChecklistLevels = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
placement: string,
|
placement: string,
|
||||||
checked: boolean
|
checked: boolean,
|
||||||
) => {
|
) => {
|
||||||
if (!listDest || listDest.length === 0) return;
|
if (!listDest || listDest.length === 0) return;
|
||||||
|
|
||||||
|
|
@ -884,7 +893,7 @@ export default function FormTeksDetail() {
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Checklist SATKER POLRI dan semua sub-item di bawahnya
|
// Checklist SATKER POLRI dan semua sub-item di bawahnya
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
currentFileLevels.add(Number(satkerItem.id));
|
currentFileLevels.add(Number(satkerItem.id));
|
||||||
|
|
@ -920,7 +929,7 @@ export default function FormTeksDetail() {
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Unchecklist SATKER POLRI dan semua sub-item di bawahnya
|
// Unchecklist SATKER POLRI dan semua sub-item di bawahnya
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
currentFileLevels.delete(Number(satkerItem.id));
|
currentFileLevels.delete(Number(satkerItem.id));
|
||||||
|
|
@ -953,7 +962,7 @@ export default function FormTeksDetail() {
|
||||||
// Fungsi untuk mengupdate checklist levels untuk file tertentu
|
// Fungsi untuk mengupdate checklist levels untuk file tertentu
|
||||||
const handleFileCheckboxChangePlacement = (
|
const handleFileCheckboxChangePlacement = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
levelId: number
|
levelId: number,
|
||||||
) => {
|
) => {
|
||||||
setFileCheckedLevels((prev) => {
|
setFileCheckedLevels((prev) => {
|
||||||
const newArray = [...prev];
|
const newArray = [...prev];
|
||||||
|
|
@ -965,7 +974,7 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
||||||
const poldaItem = listDest.find(
|
const poldaItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (
|
if (
|
||||||
poldaItem &&
|
poldaItem &&
|
||||||
|
|
@ -988,7 +997,7 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
||||||
const satkerItem = listDest.find(
|
const satkerItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
||||||
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
||||||
|
|
@ -1019,7 +1028,7 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
// Hitung total POLDA yang ada (bukan SATKER POLRI)
|
// Hitung total POLDA yang ada (bukan SATKER POLRI)
|
||||||
const totalPoldaCount = listDest.filter(
|
const totalPoldaCount = listDest.filter(
|
||||||
(item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI"
|
(item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI",
|
||||||
).length;
|
).length;
|
||||||
|
|
||||||
// Hitung berapa banyak POLDA yang ter-checklist (bukan SATKER POLRI)
|
// Hitung berapa banyak POLDA yang ter-checklist (bukan SATKER POLRI)
|
||||||
|
|
@ -1046,7 +1055,7 @@ export default function FormTeksDetail() {
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
},
|
},
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Hitung berapa banyak POLRES yang ter-checklist
|
// Hitung berapa banyak POLRES yang ter-checklist
|
||||||
|
|
@ -1056,7 +1065,7 @@ export default function FormTeksDetail() {
|
||||||
return (
|
return (
|
||||||
total +
|
total +
|
||||||
item.subDestination.filter((sub: any) =>
|
item.subDestination.filter((sub: any) =>
|
||||||
currentFileLevels.has(Number(sub.id))
|
currentFileLevels.has(Number(sub.id)),
|
||||||
).length
|
).length
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1065,7 +1074,7 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
// Cek apakah SATKER POLRI ter-checklist
|
// Cek apakah SATKER POLRI ter-checklist
|
||||||
const satkerItem = listDest.find(
|
const satkerItem = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
const isSatkerChecked =
|
const isSatkerChecked =
|
||||||
satkerItem && currentFileLevels.has(Number(satkerItem.id));
|
satkerItem && currentFileLevels.has(Number(satkerItem.id));
|
||||||
|
|
@ -1099,7 +1108,7 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
// Cek apakah semua sub-items sudah ter-checklist
|
// Cek apakah semua sub-items sudah ter-checklist
|
||||||
const allSubItemsChecked = polda.subDestination?.every((sub: any) =>
|
const allSubItemsChecked = polda.subDestination?.every((sub: any) =>
|
||||||
currentFileLevels.has(Number(sub.id))
|
currentFileLevels.has(Number(sub.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (allSubItemsChecked) {
|
if (allSubItemsChecked) {
|
||||||
|
|
@ -1182,7 +1191,7 @@ export default function FormTeksDetail() {
|
||||||
{detail &&
|
{detail &&
|
||||||
!categories.find(
|
!categories.find(
|
||||||
(cat) =>
|
(cat) =>
|
||||||
String(cat.id) === String(detail.category.id)
|
String(cat.id) === String(detail.category.id),
|
||||||
) && (
|
) && (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={String(detail.category.id)}
|
key={String(detail.category.id)}
|
||||||
|
|
@ -1465,7 +1474,7 @@ export default function FormTeksDetail() {
|
||||||
Tingkat Distribusi:
|
Tingkat Distribusi:
|
||||||
</p>
|
</p>
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||||
{[
|
{/* {[
|
||||||
{ key: "semua", label: "Semua" },
|
{ key: "semua", label: "Semua" },
|
||||||
{ key: "nasional", label: "Nasional" },
|
{ key: "nasional", label: "Nasional" },
|
||||||
{ key: "wilayah", label: "Wilayah" },
|
{ key: "wilayah", label: "Wilayah" },
|
||||||
|
|
@ -1473,6 +1482,39 @@ export default function FormTeksDetail() {
|
||||||
key: "international",
|
key: "international",
|
||||||
label: "Internasional",
|
label: "Internasional",
|
||||||
},
|
},
|
||||||
|
] */}
|
||||||
|
{[
|
||||||
|
{ key: "semua", label: "Semua" },
|
||||||
|
|
||||||
|
...(isContentFromMabesOrPolda
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
key: "nasional",
|
||||||
|
label: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "international",
|
||||||
|
label: "Internasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "wilayah",
|
||||||
|
label: "Wilayah",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
|
||||||
|
...(isContentFromSatker
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
key: "nasional",
|
||||||
|
label: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "international",
|
||||||
|
label: "Internasional",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
].map((item, idx) => (
|
].map((item, idx) => (
|
||||||
<div
|
<div
|
||||||
key={item.key}
|
key={item.key}
|
||||||
|
|
@ -1489,12 +1531,12 @@ export default function FormTeksDetail() {
|
||||||
handleFileUnitChange(
|
handleFileUnitChange(
|
||||||
index,
|
index,
|
||||||
item.key as keyof typeof unitSelection,
|
item.key as keyof typeof unitSelection,
|
||||||
value as boolean
|
value as boolean,
|
||||||
);
|
);
|
||||||
setupPlacement(
|
setupPlacement(
|
||||||
index,
|
index,
|
||||||
item.key,
|
item.key,
|
||||||
Boolean(value)
|
Boolean(value),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1510,251 +1552,262 @@ export default function FormTeksDetail() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Detail Wilayah */}
|
{/* Detail Wilayah */}
|
||||||
{fileUnitSelections[index]?.wilayah && (
|
{/* {fileUnitSelections[index]?.wilayah && ( */}
|
||||||
<div className="border-t border-gray-200 pt-2">
|
{!isContentFromSatker &&
|
||||||
<p className="text-sm font-medium text-gray-700 mb-2">
|
fileUnitSelections[index]?.wilayah && (
|
||||||
Detail Wilayah:
|
<div className="border-t border-gray-200 pt-2">
|
||||||
</p>
|
<p className="text-sm font-medium text-gray-700 mb-2">
|
||||||
|
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>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -1833,7 +1886,7 @@ export default function FormTeksDetail() {
|
||||||
>
|
>
|
||||||
{template}
|
{template}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1776,7 +1776,7 @@ export default function FormTeks() {
|
||||||
{/* <Button type="submit" color="primary">
|
{/* <Button type="submit" color="primary">
|
||||||
{t("submit", { defaultValue: "Submit" })}
|
{t("submit", { defaultValue: "Submit" })}
|
||||||
</Button> */}
|
</Button> */}
|
||||||
{levelNumber !== "2" && levelNumber !== "3" && (
|
{levelNumber !== "2" && (
|
||||||
<Button type="submit" color="primary">
|
<Button type="submit" color="primary">
|
||||||
{t("submit", { defaultValue: "Submit" })}
|
{t("submit", { defaultValue: "Submit" })}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ const ViewEditor = dynamic(
|
||||||
() => {
|
() => {
|
||||||
return import("@/components/editor/view-editor");
|
return import("@/components/editor/view-editor");
|
||||||
},
|
},
|
||||||
{ ssr: false }
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
interface Destination {
|
interface Destination {
|
||||||
|
|
@ -190,6 +190,12 @@ export default function FormVideoDetail() {
|
||||||
satker: boolean;
|
satker: boolean;
|
||||||
}>
|
}>
|
||||||
>([]);
|
>([]);
|
||||||
|
const [creatorLevelNumber, setCreatorLevelNumber] = useState<number | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
const isContentFromSatker = creatorLevelNumber === 3;
|
||||||
|
const isContentFromMabesOrPolda =
|
||||||
|
creatorLevelNumber === 1 || creatorLevelNumber === 2;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
||||||
|
|
@ -201,7 +207,7 @@ export default function FormVideoDetail() {
|
||||||
const handleFileUnitChange = (
|
const handleFileUnitChange = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
key: keyof typeof unitSelection,
|
key: keyof typeof unitSelection,
|
||||||
value: boolean
|
value: boolean,
|
||||||
) => {
|
) => {
|
||||||
setFileUnitSelections((prev) => {
|
setFileUnitSelections((prev) => {
|
||||||
const newSelections = [...prev];
|
const newSelections = [...prev];
|
||||||
|
|
@ -221,7 +227,7 @@ export default function FormVideoDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[fileIndex] || new Set()
|
newArray[fileIndex] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
@ -252,12 +258,12 @@ export default function FormVideoDetail() {
|
||||||
(item: any) =>
|
(item: any) =>
|
||||||
item.levelNumber === 2 &&
|
item.levelNumber === 2 &&
|
||||||
item.name !== "SATKER POLRI" &&
|
item.name !== "SATKER POLRI" &&
|
||||||
currentFileCheckedLevels.has(Number(item.id))
|
currentFileCheckedLevels.has(Number(item.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!hasSelectedPolda) {
|
if (!hasSelectedPolda) {
|
||||||
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; // Batalkan perubahan
|
||||||
}
|
}
|
||||||
|
|
@ -296,7 +302,7 @@ export default function FormVideoDetail() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (detail?.assignedToTopLevel) {
|
if (detail?.assignedToTopLevel) {
|
||||||
const outputSet = new Set(
|
const outputSet = new Set(
|
||||||
detail.assignedToTopLevel.split(",").map(Number)
|
detail.assignedToTopLevel.split(",").map(Number),
|
||||||
);
|
);
|
||||||
setUnitSelection({
|
setUnitSelection({
|
||||||
semua: outputSet.has(0),
|
semua: outputSet.has(0),
|
||||||
|
|
@ -321,7 +327,7 @@ export default function FormVideoDetail() {
|
||||||
acc[polda.id] = false;
|
acc[polda.id] = false;
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{}
|
{},
|
||||||
);
|
);
|
||||||
setExpandedPolda(initialExpandedState);
|
setExpandedPolda(initialExpandedState);
|
||||||
console.log("polres", initialExpandedState);
|
console.log("polres", initialExpandedState);
|
||||||
|
|
@ -356,7 +362,7 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
const handleUnitChange = (
|
const handleUnitChange = (
|
||||||
key: keyof typeof unitSelection,
|
key: keyof typeof unitSelection,
|
||||||
value: boolean
|
value: boolean,
|
||||||
) => {
|
) => {
|
||||||
if (key === "semua") {
|
if (key === "semua") {
|
||||||
const newState = {
|
const newState = {
|
||||||
|
|
@ -435,7 +441,7 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
const handleCheckboxChange = (id: number) => {
|
const handleCheckboxChange = (id: number) => {
|
||||||
setSelectedPublishers((prev) =>
|
setSelectedPublishers((prev) =>
|
||||||
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
|
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id],
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -457,7 +463,7 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
if (scheduleId && scheduleType === "3") {
|
if (scheduleId && scheduleType === "3") {
|
||||||
const findCategory = resCategory.find((o) =>
|
const findCategory = resCategory.find((o) =>
|
||||||
o.name.toLowerCase().includes("pers rilis")
|
o.name.toLowerCase().includes("pers rilis"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (findCategory) {
|
if (findCategory) {
|
||||||
|
|
@ -480,6 +486,10 @@ export default function FormVideoDetail() {
|
||||||
console.log("detail", details);
|
console.log("detail", details);
|
||||||
setFiles(details?.files);
|
setFiles(details?.files);
|
||||||
setDetail(details);
|
setDetail(details);
|
||||||
|
if (details?.uploadedBy?.userLevel?.levelNumber) {
|
||||||
|
setCreatorLevelNumber(details.uploadedBy.userLevel.levelNumber);
|
||||||
|
}
|
||||||
|
|
||||||
setMain({
|
setMain({
|
||||||
type: details?.fileType.name,
|
type: details?.fileType.name,
|
||||||
url: details?.files[0]?.url,
|
url: details?.files[0]?.url,
|
||||||
|
|
@ -489,14 +499,14 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
if (details?.assignedToLevel) {
|
if (details?.assignedToLevel) {
|
||||||
const levels = new Set(
|
const levels = new Set(
|
||||||
details.assignedToLevel.split(",").map(Number)
|
details.assignedToLevel.split(",").map(Number),
|
||||||
);
|
);
|
||||||
setCheckedLevels(levels);
|
setCheckedLevels(levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (details?.publishedForObject) {
|
if (details?.publishedForObject) {
|
||||||
const publisherIds = details?.publishedForObject?.map(
|
const publisherIds = details?.publishedForObject?.map(
|
||||||
(obj: any) => obj.id
|
(obj: any) => obj.id,
|
||||||
);
|
);
|
||||||
setSelectedPublishers(publisherIds);
|
setSelectedPublishers(publisherIds);
|
||||||
}
|
}
|
||||||
|
|
@ -506,7 +516,7 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
const filesData = details?.files || [];
|
const filesData = details?.files || [];
|
||||||
const fileUrls = filesData.map((files: { url: string }) =>
|
const fileUrls = filesData.map((files: { url: string }) =>
|
||||||
files.url ? files.url : "default-image.jpg"
|
files.url ? files.url : "default-image.jpg",
|
||||||
);
|
);
|
||||||
setDetailVideo(fileUrls);
|
setDetailVideo(fileUrls);
|
||||||
|
|
||||||
|
|
@ -684,7 +694,7 @@ export default function FormVideoDetail() {
|
||||||
const setupPlacement = (
|
const setupPlacement = (
|
||||||
index: number,
|
index: number,
|
||||||
placement: string,
|
placement: string,
|
||||||
checked: boolean
|
checked: boolean,
|
||||||
) => {
|
) => {
|
||||||
let temp = [...filePlacements];
|
let temp = [...filePlacements];
|
||||||
if (checked) {
|
if (checked) {
|
||||||
|
|
@ -695,7 +705,7 @@ export default function FormVideoDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[index] || new Set()
|
newArray[index] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Checklist semua item di modal
|
// Checklist semua item di modal
|
||||||
|
|
@ -745,7 +755,7 @@ export default function FormVideoDetail() {
|
||||||
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
||||||
// JANGAN include satker dalam perhitungan auto "all"
|
// JANGAN include satker dalam perhitungan auto "all"
|
||||||
const nonSatkerItems = now.filter(
|
const nonSatkerItems = now.filter(
|
||||||
(item) => item !== "satker" && item !== "all"
|
(item) => item !== "satker" && item !== "all",
|
||||||
);
|
);
|
||||||
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
||||||
now.push("all");
|
now.push("all");
|
||||||
|
|
@ -760,7 +770,7 @@ export default function FormVideoDetail() {
|
||||||
setFileCheckedLevels((prevLevels) => {
|
setFileCheckedLevels((prevLevels) => {
|
||||||
const newArray = [...prevLevels];
|
const newArray = [...prevLevels];
|
||||||
const currentFileLevels = new Set<number>(
|
const currentFileLevels = new Set<number>(
|
||||||
newArray[index] || new Set()
|
newArray[index] || new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Unchecklist semua item di modal
|
// Unchecklist semua item di modal
|
||||||
|
|
@ -794,7 +804,7 @@ export default function FormVideoDetail() {
|
||||||
// Hapus "all" jika tidak semua item ter-checklist
|
// Hapus "all" jika tidak semua item ter-checklist
|
||||||
if (now.includes("all")) {
|
if (now.includes("all")) {
|
||||||
const nonSatkerItems = now.filter(
|
const nonSatkerItems = now.filter(
|
||||||
(item) => item !== "satker" && item !== "all"
|
(item) => item !== "satker" && item !== "all",
|
||||||
);
|
);
|
||||||
if (nonSatkerItems.length < 3) {
|
if (nonSatkerItems.length < 3) {
|
||||||
const newData = now.filter((b) => b !== "all");
|
const newData = now.filter((b) => b !== "all");
|
||||||
|
|
@ -812,7 +822,7 @@ export default function FormVideoDetail() {
|
||||||
const updateModalChecklistLevels = (
|
const updateModalChecklistLevels = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
placement: string,
|
placement: string,
|
||||||
checked: boolean
|
checked: boolean,
|
||||||
) => {
|
) => {
|
||||||
if (!listDest || listDest.length === 0) return;
|
if (!listDest || listDest.length === 0) return;
|
||||||
|
|
||||||
|
|
@ -845,7 +855,7 @@ export default function FormVideoDetail() {
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Checklist SATKER POLRI dan semua sub-item di bawahnya
|
// Checklist SATKER POLRI dan semua sub-item di bawahnya
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
currentFileLevels.add(Number(satkerItem.id));
|
currentFileLevels.add(Number(satkerItem.id));
|
||||||
|
|
@ -881,7 +891,7 @@ export default function FormVideoDetail() {
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Unchecklist SATKER POLRI dan semua sub-item di bawahnya
|
// Unchecklist SATKER POLRI dan semua sub-item di bawahnya
|
||||||
const satkerItem: any = listDest.find(
|
const satkerItem: any = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
if (satkerItem) {
|
if (satkerItem) {
|
||||||
currentFileLevels.delete(Number(satkerItem.id));
|
currentFileLevels.delete(Number(satkerItem.id));
|
||||||
|
|
@ -910,7 +920,7 @@ export default function FormVideoDetail() {
|
||||||
type: string,
|
type: string,
|
||||||
url: string,
|
url: string,
|
||||||
names: string,
|
names: string,
|
||||||
format: string
|
format: string,
|
||||||
) => {
|
) => {
|
||||||
console.log("Test 3 :", type, url, names, format);
|
console.log("Test 3 :", type, url, names, format);
|
||||||
setMain({
|
setMain({
|
||||||
|
|
@ -951,7 +961,7 @@ export default function FormVideoDetail() {
|
||||||
// Fungsi untuk mengupdate checklist levels untuk file tertentu
|
// Fungsi untuk mengupdate checklist levels untuk file tertentu
|
||||||
const handleFileCheckboxChangePlacement = (
|
const handleFileCheckboxChangePlacement = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
levelId: number
|
levelId: number,
|
||||||
) => {
|
) => {
|
||||||
setFileCheckedLevels((prev) => {
|
setFileCheckedLevels((prev) => {
|
||||||
const newArray = [...prev];
|
const newArray = [...prev];
|
||||||
|
|
@ -963,7 +973,7 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
// Jika ini adalah POLDA yang di-unchecklist, unchecklist juga semua polres di bawahnya
|
||||||
const poldaItem = listDest.find(
|
const poldaItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (
|
if (
|
||||||
poldaItem &&
|
poldaItem &&
|
||||||
|
|
@ -986,7 +996,7 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
// Jika ini adalah SATKER POLRI yang di-checklist, checklist juga semua sub-item di bawahnya
|
||||||
const satkerItem = listDest.find(
|
const satkerItem = listDest.find(
|
||||||
(item: any) => Number(item.id) === levelId
|
(item: any) => Number(item.id) === levelId,
|
||||||
) as any;
|
) as any;
|
||||||
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
if (satkerItem && satkerItem.name === "SATKER POLRI") {
|
||||||
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
// Checklist semua sub-item di bawah SATKER POLRI (bukan POLRES)
|
||||||
|
|
@ -1017,7 +1027,7 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
// Hitung total POLDA yang ada (bukan SATKER POLRI)
|
// Hitung total POLDA yang ada (bukan SATKER POLRI)
|
||||||
const totalPoldaCount = listDest.filter(
|
const totalPoldaCount = listDest.filter(
|
||||||
(item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI"
|
(item: any) => item.levelNumber === 2 && item.name !== "SATKER POLRI",
|
||||||
).length;
|
).length;
|
||||||
|
|
||||||
// Hitung berapa banyak POLDA yang ter-checklist (bukan SATKER POLRI)
|
// Hitung berapa banyak POLDA yang ter-checklist (bukan SATKER POLRI)
|
||||||
|
|
@ -1044,7 +1054,7 @@ export default function FormVideoDetail() {
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
},
|
},
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Hitung berapa banyak POLRES yang ter-checklist
|
// Hitung berapa banyak POLRES yang ter-checklist
|
||||||
|
|
@ -1054,7 +1064,7 @@ export default function FormVideoDetail() {
|
||||||
return (
|
return (
|
||||||
total +
|
total +
|
||||||
item.subDestination.filter((sub: any) =>
|
item.subDestination.filter((sub: any) =>
|
||||||
currentFileLevels.has(Number(sub.id))
|
currentFileLevels.has(Number(sub.id)),
|
||||||
).length
|
).length
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1063,7 +1073,7 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
// Cek apakah SATKER POLRI ter-checklist
|
// Cek apakah SATKER POLRI ter-checklist
|
||||||
const satkerItem = listDest.find(
|
const satkerItem = listDest.find(
|
||||||
(item: any) => item.name === "SATKER POLRI"
|
(item: any) => item.name === "SATKER POLRI",
|
||||||
);
|
);
|
||||||
const isSatkerChecked =
|
const isSatkerChecked =
|
||||||
satkerItem && currentFileLevels.has(Number(satkerItem.id));
|
satkerItem && currentFileLevels.has(Number(satkerItem.id));
|
||||||
|
|
@ -1097,7 +1107,7 @@ export default function FormVideoDetail() {
|
||||||
|
|
||||||
// Cek apakah semua sub-items sudah ter-checklist
|
// Cek apakah semua sub-items sudah ter-checklist
|
||||||
const allSubItemsChecked = polda.subDestination?.every((sub: any) =>
|
const allSubItemsChecked = polda.subDestination?.every((sub: any) =>
|
||||||
currentFileLevels.has(Number(sub.id))
|
currentFileLevels.has(Number(sub.id)),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (allSubItemsChecked) {
|
if (allSubItemsChecked) {
|
||||||
|
|
@ -1180,7 +1190,7 @@ export default function FormVideoDetail() {
|
||||||
{detail &&
|
{detail &&
|
||||||
!categories.find(
|
!categories.find(
|
||||||
(cat) =>
|
(cat) =>
|
||||||
String(cat.id) === String(detail.category.id)
|
String(cat.id) === String(detail.category.id),
|
||||||
) && (
|
) && (
|
||||||
<SelectItem
|
<SelectItem
|
||||||
key={String(detail.category.id)}
|
key={String(detail.category.id)}
|
||||||
|
|
@ -1465,7 +1475,7 @@ export default function FormVideoDetail() {
|
||||||
Tingkat Distribusi:
|
Tingkat Distribusi:
|
||||||
</p>
|
</p>
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||||
{[
|
{/* {[
|
||||||
{ key: "semua", label: "Semua" },
|
{ key: "semua", label: "Semua" },
|
||||||
{ key: "nasional", label: "Nasional" },
|
{ key: "nasional", label: "Nasional" },
|
||||||
{ key: "wilayah", label: "Wilayah" },
|
{ key: "wilayah", label: "Wilayah" },
|
||||||
|
|
@ -1473,6 +1483,39 @@ export default function FormVideoDetail() {
|
||||||
key: "international",
|
key: "international",
|
||||||
label: "Internasional",
|
label: "Internasional",
|
||||||
},
|
},
|
||||||
|
] */}
|
||||||
|
{[
|
||||||
|
{ key: "semua", label: "Semua" },
|
||||||
|
|
||||||
|
...(isContentFromMabesOrPolda
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
key: "nasional",
|
||||||
|
label: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "international",
|
||||||
|
label: "Internasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "wilayah",
|
||||||
|
label: "Wilayah",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
|
||||||
|
...(isContentFromSatker
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
key: "nasional",
|
||||||
|
label: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "international",
|
||||||
|
label: "Internasional",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
].map((item, idx) => (
|
].map((item, idx) => (
|
||||||
<div
|
<div
|
||||||
key={item.key}
|
key={item.key}
|
||||||
|
|
@ -1489,12 +1532,12 @@ export default function FormVideoDetail() {
|
||||||
handleFileUnitChange(
|
handleFileUnitChange(
|
||||||
index,
|
index,
|
||||||
item.key as keyof typeof unitSelection,
|
item.key as keyof typeof unitSelection,
|
||||||
value as boolean
|
value as boolean,
|
||||||
);
|
);
|
||||||
setupPlacement(
|
setupPlacement(
|
||||||
index,
|
index,
|
||||||
item.key,
|
item.key,
|
||||||
Boolean(value)
|
Boolean(value),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1510,251 +1553,262 @@ export default function FormVideoDetail() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Detail Wilayah */}
|
{/* Detail Wilayah */}
|
||||||
{fileUnitSelections[index]?.wilayah && (
|
{/* {fileUnitSelections[index]?.wilayah && ( */}
|
||||||
<div className="border-t border-gray-200 pt-2">
|
{!isContentFromSatker &&
|
||||||
<p className="text-sm font-medium text-gray-700 mb-2">
|
fileUnitSelections[index]?.wilayah && (
|
||||||
Detail Wilayah:
|
<div className="border-t border-gray-200 pt-2">
|
||||||
</p>
|
<p className="text-sm font-medium text-gray-700 mb-2">
|
||||||
|
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>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -1833,7 +1887,7 @@ export default function FormVideoDetail() {
|
||||||
>
|
>
|
||||||
{template}
|
{template}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ const CustomEditor = dynamic(
|
||||||
() => {
|
() => {
|
||||||
return import("@/components/editor/custom-editor");
|
return import("@/components/editor/custom-editor");
|
||||||
},
|
},
|
||||||
{ ssr: false }
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
interface FileWithPreview extends File {
|
interface FileWithPreview extends File {
|
||||||
|
|
@ -111,11 +111,11 @@ export default function FormVideo() {
|
||||||
const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
|
const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
|
||||||
const [articleBody, setArticleBody] = useState<string>("");
|
const [articleBody, setArticleBody] = useState<string>("");
|
||||||
const [selectedArticleId, setSelectedArticleId] = useState<string | null>(
|
const [selectedArticleId, setSelectedArticleId] = useState<string | null>(
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
||||||
const [publishedForError, setPublishedForError] = useState<string | null>(
|
const [publishedForError, setPublishedForError] = useState<string | null>(
|
||||||
null
|
null,
|
||||||
);
|
);
|
||||||
const [selectedSize, setSelectedSize] = useState("");
|
const [selectedSize, setSelectedSize] = useState("");
|
||||||
const [detailData, setDetailData] = useState<any>(null);
|
const [detailData, setDetailData] = useState<any>(null);
|
||||||
|
|
@ -184,7 +184,7 @@ export default function FormVideo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const filesWithPreview = acceptedFiles.map((file) =>
|
const filesWithPreview = acceptedFiles.map((file) =>
|
||||||
Object.assign(file, { preview: URL.createObjectURL(file) })
|
Object.assign(file, { preview: URL.createObjectURL(file) }),
|
||||||
);
|
);
|
||||||
|
|
||||||
setFiles((prev) => {
|
setFiles((prev) => {
|
||||||
|
|
@ -211,11 +211,11 @@ export default function FormVideo() {
|
||||||
.refine(
|
.refine(
|
||||||
(files) =>
|
(files) =>
|
||||||
files.every((file: File) => ACCEPTED_FILE_TYPES.includes(file.type)),
|
files.every((file: File) => ACCEPTED_FILE_TYPES.includes(file.type)),
|
||||||
{ message: "File harus berformat mp4 atau mov" }
|
{ message: "File harus berformat mp4 atau mov" },
|
||||||
)
|
)
|
||||||
.refine(
|
.refine(
|
||||||
(files) => files.every((file: File) => file.size <= MAX_FILE_SIZE),
|
(files) => files.every((file: File) => file.size <= MAX_FILE_SIZE),
|
||||||
{ message: "Ukuran file maksimal 100 MB" }
|
{ message: "Ukuran file maksimal 100 MB" },
|
||||||
),
|
),
|
||||||
publishedFor: z
|
publishedFor: z
|
||||||
.array(z.string())
|
.array(z.string())
|
||||||
|
|
@ -423,7 +423,7 @@ export default function FormVideo() {
|
||||||
const articleData = await waitForStatusUpdate();
|
const articleData = await waitForStatusUpdate();
|
||||||
const cleanArticleBody = articleData?.articleBody?.replace(
|
const cleanArticleBody = articleData?.articleBody?.replace(
|
||||||
/<img[^>]*>/g,
|
/<img[^>]*>/g,
|
||||||
""
|
"",
|
||||||
);
|
);
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
setValue("description", cleanArticleBody || "");
|
setValue("description", cleanArticleBody || "");
|
||||||
|
|
@ -479,7 +479,7 @@ export default function FormVideo() {
|
||||||
|
|
||||||
if (scheduleId && scheduleType === "3") {
|
if (scheduleId && scheduleType === "3") {
|
||||||
const findCategory = resCategory.find((o) =>
|
const findCategory = resCategory.find((o) =>
|
||||||
o.name.toLowerCase().includes("pers rilis")
|
o.name.toLowerCase().includes("pers rilis"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (findCategory) {
|
if (findCategory) {
|
||||||
|
|
@ -502,7 +502,7 @@ export default function FormVideo() {
|
||||||
setPublishedFor(
|
setPublishedFor(
|
||||||
options
|
options
|
||||||
.filter((opt: any) => opt.id !== "all")
|
.filter((opt: any) => opt.id !== "all")
|
||||||
.map((opt: any) => opt.id)
|
.map((opt: any) => opt.id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -561,8 +561,8 @@ export default function FormVideo() {
|
||||||
translatedTitle && translatedTitle.trim() !== ""
|
translatedTitle && translatedTitle.trim() !== ""
|
||||||
? translatedTitle
|
? translatedTitle
|
||||||
: isSwitchOn
|
: isSwitchOn
|
||||||
? title
|
? title
|
||||||
: data.title;
|
: data.title;
|
||||||
|
|
||||||
// Tentukan deskripsi final:
|
// Tentukan deskripsi final:
|
||||||
// Jika ada hasil translate, kirim itu ke backend
|
// Jika ada hasil translate, kirim itu ke backend
|
||||||
|
|
@ -570,10 +570,10 @@ export default function FormVideo() {
|
||||||
translatedContent && translatedContent.trim() !== ""
|
translatedContent && translatedContent.trim() !== ""
|
||||||
? translatedContent
|
? translatedContent
|
||||||
: isSwitchOn
|
: isSwitchOn
|
||||||
? data.description
|
? data.description
|
||||||
: selectedFileType === "rewrite"
|
: selectedFileType === "rewrite"
|
||||||
? data.rewriteDescription
|
? data.rewriteDescription
|
||||||
: data.descriptionOri;
|
: data.descriptionOri;
|
||||||
|
|
||||||
if (!finalDescription?.trim()) {
|
if (!finalDescription?.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
|
|
@ -695,7 +695,7 @@ export default function FormVideo() {
|
||||||
idx: number,
|
idx: number,
|
||||||
id: string,
|
id: string,
|
||||||
file: any,
|
file: any,
|
||||||
duration: string
|
duration: string,
|
||||||
) {
|
) {
|
||||||
console.log(idx, id, file, duration);
|
console.log(idx, id, file, duration);
|
||||||
|
|
||||||
|
|
@ -731,7 +731,7 @@ export default function FormVideo() {
|
||||||
onChunkComplete: (
|
onChunkComplete: (
|
||||||
chunkSize: any,
|
chunkSize: any,
|
||||||
bytesAccepted: any,
|
bytesAccepted: any,
|
||||||
bytesTotal: any
|
bytesTotal: any,
|
||||||
) => {
|
) => {
|
||||||
const uploadPersen = Math.floor((bytesAccepted / bytesTotal) * 100);
|
const uploadPersen = Math.floor((bytesAccepted / bytesTotal) * 100);
|
||||||
progressInfo[idx].percentage = uploadPersen;
|
progressInfo[idx].percentage = uploadPersen;
|
||||||
|
|
@ -791,8 +791,8 @@ export default function FormVideo() {
|
||||||
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const file = e.target.files?.[0];
|
const file = e.target.files?.[0];
|
||||||
if (file) {
|
if (file) {
|
||||||
setThumbnail(file);
|
setThumbnail(file);
|
||||||
setPreview(URL.createObjectURL(file));
|
setPreview(URL.createObjectURL(file));
|
||||||
console.log("Selected Thumbnail:", file);
|
console.log("Selected Thumbnail:", file);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -823,7 +823,7 @@ export default function FormVideo() {
|
||||||
<div
|
<div
|
||||||
key={file.name}
|
key={file.name}
|
||||||
className=" flex justify-between border px-3.5 py-3 my-6 rounded-md"
|
className=" flex justify-between border px-3.5 py-3 my-6 rounded-md"
|
||||||
>
|
>
|
||||||
<div className="flex gap-3 items-center">
|
<div className="flex gap-3 items-center">
|
||||||
{/* <div className="file-preview">{renderFilePreview(file)}</div> */}
|
{/* <div className="file-preview">{renderFilePreview(file)}</div> */}
|
||||||
<svg
|
<svg
|
||||||
|
|
@ -1732,7 +1732,7 @@ export default function FormVideo() {
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const updatedTags = field.value.filter(
|
const updatedTags = field.value.filter(
|
||||||
(_, i) => i !== index
|
(_, i) => i !== index,
|
||||||
);
|
);
|
||||||
field.onChange(updatedTags);
|
field.onChange(updatedTags);
|
||||||
}}
|
}}
|
||||||
|
|
@ -1825,7 +1825,7 @@ export default function FormVideo() {
|
||||||
{/* <Button type="submit" color="primary">
|
{/* <Button type="submit" color="primary">
|
||||||
{t("submit", { defaultValue: "Submit" })}
|
{t("submit", { defaultValue: "Submit" })}
|
||||||
</Button> */}
|
</Button> */}
|
||||||
{levelNumber !== "2" && levelNumber !== "3" && (
|
{levelNumber !== "2" && (
|
||||||
<Button type="submit" color="primary">
|
<Button type="submit" color="primary">
|
||||||
{t("submit", { defaultValue: "Submit" })}
|
{t("submit", { defaultValue: "Submit" })}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export const GoogleMapsAPI = "AIzaSyCuQHorDceMCzlSgrB9AEY5ns8KeriFsME";
|
// export const GoogleMapsAPI = "AIzaSyCuQHorDceMCzlSgrB9AEY5ns8KeriFsME";
|
||||||
|
export const GoogleMapsAPI = "AIzaSyA-Dci9RP4ZjyJCFfy74WvhtMZXSDLTPMQ";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue