diff --git a/app/[locale]/sitemap.xml/route.ts b/app/[locale]/sitemap.xml/route.ts new file mode 100644 index 00000000..27a798b0 --- /dev/null +++ b/app/[locale]/sitemap.xml/route.ts @@ -0,0 +1,64 @@ +"use server"; +import { getListContent } from "@/service/landing/landing"; +import { NextResponse } from "next/server"; + +export async function GET() { + try { + const baseUrl = "https://mediahub.polri.go.id/in"; + + const response = await getListContent({ + page: 1, + limit: "100", + search: "", + }); + const articles = response?.data?.data || []; + + const urls = articles + .map((article: any) => { + const type = + article.fileTypeId == 1 + ? "image" + : article.fileTypeId == 2 + ? "video" + : article.fileTypeId == 3 + ? "document" + : "audio"; + + const slug = article.slug + ? encodeURIComponent(article.slug) + : article.id; + const lastmod = article.updatedAt + ? new Date(article.updatedAt).toISOString() + : new Date().toISOString(); + + return ` + + ${baseUrl}/${type}/detail/${article.id}-${slug} + ${lastmod} + weekly + 0.8 + `; + }) + .join("\n"); + + const sitemap = ` + + + ${baseUrl} + ${new Date().toISOString()} + daily + 1.0 + +${urls} +`; + + return new NextResponse(sitemap, { + headers: { + "Content-Type": "application/xml", + }, + }); + } catch (error: any) { + console.error("Sitemap error:", error); + return new NextResponse("Sitemap generation failed", { status: 500 }); + } +} diff --git a/app/sitemap.xml/route.ts b/app/sitemap.xml/route.ts deleted file mode 100644 index 09b026e8..00000000 --- a/app/sitemap.xml/route.ts +++ /dev/null @@ -1,40 +0,0 @@ -"use server"; -import { getListContent } from "@/service/landing/landing"; -import { NextResponse } from "next/server"; - -export async function GET() { - const baseUrl = "https://mediahub.polri.go.id/in"; - - const response = await getListContent({ page: 1, limit: "100", search: "" }); - - const articles = response?.data?.data || []; - - const urls = articles - .map( - (article: any) => ` - - ${baseUrl}/${article.fileTypeId == 1 ? "image" : article.fileTypeId == 2 ? "video" : article.fileTypeId == 3 ? "document" : "audio"}/detail/${article.id}-${article.slug} - ${new Date(article.updatedAt).toISOString()} - weekly - 0.8 - ` - ) - .join(""); - - const sitemap = ` - - - ${baseUrl} - ${new Date().toISOString()} - daily - 1.0 - - ${urls} - `; - - return new NextResponse(sitemap, { - headers: { - "Content-Type": "application/xml", - }, - }); -} diff --git a/components/form/content/audio-update-form.tsx b/components/form/content/audio-update-form.tsx index e15cd23c..cd43b640 100644 --- a/components/form/content/audio-update-form.tsx +++ b/components/form/content/audio-update-form.tsx @@ -762,19 +762,26 @@ export default function FormAudioUpdate() { const getPlacement = () => { const temp = []; for (let i = 0; i < filePlacements?.length; i++) { - if (filePlacements[i]?.length !== 0) { - const now = filePlacements[i]; - let nowArr = now?.join(",")?.replaceAll("nasional", "mabes"); - nowArr = nowArr?.replaceAll("wilayah", "polda"); - nowArr = nowArr?.replaceAll("semua", "all"); + const file = files[i] as any; + if (file.id && filePlacements[file.id] && filePlacements[file.id].length > 0) { + const now = filePlacements[file.id]; + const normalizedNow = now.map((item): PlacementType => { + const value = String(item); + if (value === "nasional") return "mabes"; + if (value === "wilayah") return "polda"; + if (value === "semua") return "all"; + return item as PlacementType; + }); + const uniqueNow = Array.from(new Set(normalizedNow)); + const nowArr = uniqueNow.join(","); // Dapatkan checked levels untuk file ini - const currentFileCheckedLevels = fileCheckedLevels[i] - ? Array.from(fileCheckedLevels[i]) + const currentFileCheckedLevels = fileCheckedLevels[file.id] + ? Array.from(fileCheckedLevels[file.id]) : []; const data = { - mediaFileId: files[i]?.id, + mediaFileId: file.id, placements: nowArr, customLocationPlacements: currentFileCheckedLevels.join(","), }; @@ -859,12 +866,20 @@ export default function FormAudioUpdate() { } temp[index] = now; } else { + // Handle mapping dari UI key ke backend value + let placementToAdd = placement; + if (placement === "nasional") { + placementToAdd = "mabes"; + } else if (placement === "semua") { + placementToAdd = "all"; + } + const now = temp[index] || []; - if (!now.includes(placement)) { - now.push(placement); + if (!now.includes(placementToAdd)) { + now.push(placementToAdd); } // Auto-checklist "all" jika nasional, wilayah, dan international ter-checklist - const requiredItems = ["nasional", "wilayah", "international"]; + const requiredItems = ["mabes", "wilayah", "international"]; const hasAllRequired = requiredItems.every(item => now.includes(item)); if (hasAllRequired && !now.includes("all")) { now.push("all"); @@ -921,14 +936,22 @@ export default function FormAudioUpdate() { const now = temp[index]?.filter((a) => a !== "satker"); temp[index] = now; } else { - const now = temp[index]?.filter((a) => a !== placement); + // Handle mapping dari UI key ke backend value + let placementToRemove = placement; + if (placement === "nasional") { + placementToRemove = "mabes"; + } else if (placement === "semua") { + placementToRemove = "all"; + } + + const now = temp[index]?.filter((a) => a !== placementToRemove); temp[index] = now; } // Hapus "all" jika tidak semua item ter-checklist const currentNow = temp[index] || []; if (currentNow.includes("all")) { - const requiredItems = ["nasional", "wilayah", "international"]; + const requiredItems = ["mabes", "wilayah", "international"]; const hasAllRequired = requiredItems.every(item => currentNow.includes(item)); if (!hasAllRequired) { const newData = currentNow.filter((b) => b !== "all"); @@ -1108,9 +1131,11 @@ export default function FormAudioUpdate() { } if (placements.includes("polda")) { selection.polda = true; + selection.wilayah = true; // Auto-check wilayah when polda is present } if (placements.includes("satker")) { selection.satker = true; + selection.wilayah = true; // Auto-check wilayah when satker is present } if (placements.includes("international")) { selection.international = true; @@ -1608,56 +1633,352 @@ export default function FormAudioUpdate() {
{files.map((file: any, index: any) => ( -
-
- - - {" "} -
-
- {file.fileName || file.name} +
+ -
- {Math.round(file.size / 100) / 10 > 1000 ? ( - <> - {( - Math.round(file.size / 100) / 10000 - ).toFixed(1)} +
+ {/* Checkbox Tingkat Utama */} +
+
+ {[ + { key: "semua", label: "Semua" }, + { + key: "nasional", + label: "Nasional", + }, + { key: "wilayah", label: "Wilayah" }, + { + key: "international", + label: "Internasional", + }, + ].map((item, idx) => ( +
+ { + handleFileUnitChange( + index, + item.key as keyof typeof unitSelection, + value as boolean + ); + setupPlacement( + index, + item.key, + Boolean(value) + ); + }} + /> + +
+ ))} +
+ + {/* Detail Wilayah */} + {fileUnitSelections[index]?.wilayah && isDetailOfRegionShowed && ( +
+

+ Detail Wilayah: +

+ + {/* Checkbox Sub-kategori dengan tombol Kustom sejajar */} +
+ {[ + { key: "polda", label: "POLDA" }, + { key: "satker", label: "SATKER" }, + ].map((item, idx) => ( +
+ { + handleFileUnitChange( + index, + item.key as keyof typeof unitSelection, + value as boolean + ); + setupPlacement( + index, + item.key, + Boolean(value) + ); + }} + /> + +
+ ))} + + {/* Tombol Kustom sejajar dengan checkbox */} +
+ + + + + + + + Daftar Wilayah POLDA dan SATKER + + +
+ {listDest.map( + (polda: any) => ( +
+ {/* Header POLDA */} +
+ + {/* Tombol expand hanya untuk SATKER POLRI */} + {polda.name === "SATKER POLRI" && polda.subDestination && ( + + )} +
+ + {/* Sub-items hanya untuk SATKER POLRI */} + {polda.name === "SATKER POLRI" && polda.subDestination && + expandedPolda[ + polda.id + ] && ( +
+ {/* Tombol Pilih Semua untuk sub-items */} +
+ {(() => { + const allSubItemsChecked = + polda.subDestination?.every( + ( + sub: any + ) => + fileCheckedLevels[ + index + ]?.has( + Number( + sub.id + ) + ) + ); + return ( + + ); + })()}
+
+ {polda.subDestination.map( + ( + sub: any + ) => ( + + ) + )}
+ )} -
+ ) + )} +
+
+ + + + + + +
+
+
+
+
+
+ )} +
+
+
- ))} + ))}
)} diff --git a/components/form/content/image-update-form.tsx b/components/form/content/image-update-form.tsx index bfe3bf03..2b434176 100644 --- a/components/form/content/image-update-form.tsx +++ b/components/form/content/image-update-form.tsx @@ -489,8 +489,8 @@ export default function FormImageUpdate() { }); } } else { - // Update salah satu saja - currentSelection[key] = value; + // Update salah satu saja + currentSelection[key] = value; } // Cek apakah semua selain "semua" sudah dicentang @@ -889,9 +889,11 @@ export default function FormImageUpdate() { } if (placements.includes("polda")) { selection.polda = true; + selection.wilayah = true; // Auto-check wilayah when polda is present } if (placements.includes("satker")) { selection.satker = true; + selection.wilayah = true; // Auto-check wilayah when satker is present } if (placements.includes("international")) { selection.international = true; @@ -937,19 +939,26 @@ export default function FormImageUpdate() { const getPlacement = () => { const temp = []; for (let i = 0; i < filePlacements?.length; i++) { - if (filePlacements[i]?.length !== 0) { - const now = filePlacements[i]; - let nowArr = now?.join(",")?.replaceAll("nasional", "mabes"); - nowArr = nowArr?.replaceAll("wilayah", "polda"); - nowArr = nowArr?.replaceAll("semua", "all"); + const file = files[i] as any; + if (file.id && filePlacements[file.id] && filePlacements[file.id].length > 0) { + const now = filePlacements[file.id]; + const normalizedNow = now.map((item): PlacementType => { + const value = String(item); + if (value === "nasional") return "mabes"; + if (value === "wilayah") return "polda"; + if (value === "semua") return "all"; + return item as PlacementType; + }); + const uniqueNow = Array.from(new Set(normalizedNow)); + const nowArr = uniqueNow.join(","); // Dapatkan checked levels untuk file ini - const currentFileCheckedLevels = fileCheckedLevels[i] - ? Array.from(fileCheckedLevels[i]) + const currentFileCheckedLevels = fileCheckedLevels[file.id] + ? Array.from(fileCheckedLevels[file.id]) : []; const data = { - mediaFileId: files[i]?.id, + mediaFileId: file.id, placements: nowArr, customLocationPlacements: currentFileCheckedLevels.join(","), }; @@ -1548,6 +1557,25 @@ export default function FormImageUpdate() { const now = temp[index]?.filter((a) => a !== placement); console.log("now", now); temp[index] = now; + if (placement === "wilayah") { + // Ketika wilayah di-uncheck, hapus wilayah, polda, dan satker + const now = temp[index]?.filter((a) => + a !== "wilayah" && a !== "polda" && a !== "satker" + ); + temp[index] = now; + } else if (placement === "polda") { + // Ketika polda di-uncheck, hapus polda dari filePlacements + const now = temp[index]?.filter((a) => a !== "polda"); + temp[index] = now; + } else if (placement === "satker") { + // Ketika satker di-uncheck, hapus satker dari filePlacements + const now = temp[index]?.filter((a) => a !== "satker"); + temp[index] = now; + } else { + const now = temp[index]?.filter((a) => a !== placement); + temp[index] = now; + } + // Hapus "all" jika tidak semua item ter-checklist if (now.includes("all")) { const nonSatkerItems = now.filter( diff --git a/components/form/content/teks-update-form.tsx b/components/form/content/teks-update-form.tsx index 9a17e843..b0ebdc0f 100644 --- a/components/form/content/teks-update-form.tsx +++ b/components/form/content/teks-update-form.tsx @@ -804,25 +804,31 @@ export default function FormTeksUpdate() { }; const getPlacement = () => { - const temp = []; - for (let i = 0; i < filePlacements?.length; i++) { - if (filePlacements[i]?.length !== 0) { - const now = filePlacements[i]; - let nowArr = now?.join(",")?.replaceAll("nasional", "mabes"); - nowArr = nowArr?.replaceAll("wilayah", "polda"); - nowArr = nowArr?.replaceAll("semua", "all"); + const temp: Array<{ mediaFileId: number | string; placements: string; customLocationPlacements: string }> = []; + for (let i = 0; i < files.length; i++) { + const file = files[i] as any; + const now = filePlacements[i]; + if (file?.id && Array.isArray(now) && now.length > 0) { + const normalizedNow = now.map((item): PlacementType => { + const value = String(item); + if (value === "nasional") return "mabes"; + if (value === "wilayah") return "polda"; + if (value === "semua") return "all"; + return item as PlacementType; + }); + const uniqueNow = Array.from(new Set(normalizedNow)); + const nowArr = uniqueNow.join(","); - // Dapatkan checked levels untuk file ini + // Dapatkan checked levels untuk file ini (berbasis index) const currentFileCheckedLevels = fileCheckedLevels[i] ? Array.from(fileCheckedLevels[i]) : []; - const data = { - mediaFileId: files[i]?.id, + temp.push({ + mediaFileId: file.id, placements: nowArr, customLocationPlacements: currentFileCheckedLevels.join(","), - }; - temp.push(data); + }); } } return temp; @@ -903,12 +909,20 @@ export default function FormTeksUpdate() { } temp[index] = now; } else { + // Handle mapping dari UI key ke backend value + let placementToAdd = placement; + if (placement === "nasional") { + placementToAdd = "mabes"; + } else if (placement === "semua") { + placementToAdd = "all"; + } + const now = temp[index] || []; - if (!now.includes(placement)) { - now.push(placement); + if (!now.includes(placementToAdd)) { + now.push(placementToAdd); } // Auto-checklist "all" jika nasional, wilayah, dan international ter-checklist - const requiredItems = ["nasional", "wilayah", "international"]; + const requiredItems = ["mabes", "wilayah", "international"]; const hasAllRequired = requiredItems.every(item => now.includes(item)); if (hasAllRequired && !now.includes("all")) { now.push("all"); @@ -965,14 +979,22 @@ export default function FormTeksUpdate() { const now = temp[index]?.filter((a) => a !== "satker"); temp[index] = now; } else { - const now = temp[index]?.filter((a) => a !== placement); + // Handle mapping dari UI key ke backend value + let placementToRemove = placement; + if (placement === "nasional") { + placementToRemove = "mabes"; + } else if (placement === "semua") { + placementToRemove = "all"; + } + + const now = temp[index]?.filter((a) => a !== placementToRemove); temp[index] = now; } // Hapus "all" jika tidak semua item ter-checklist const currentNow = temp[index] || []; if (currentNow.includes("all")) { - const requiredItems = ["nasional", "wilayah", "international"]; + const requiredItems = ["mabes", "wilayah", "international"]; const hasAllRequired = requiredItems.every(item => currentNow.includes(item)); if (!hasAllRequired) { const newData = currentNow.filter((b) => b !== "all"); @@ -1084,11 +1106,10 @@ export default function FormTeksUpdate() { })); setFiles(formattedFiles); - // Inisialisasi filePlacements dari detail + // Inisialisasi filePlacements dari detail (biarkan format backend, normalisasi dilakukan saat submit) const initialFilePlacements: string[][] = details.files.map((file: any) => { if (file.placements) { - const placements = file.placements.split(",").map((p: string) => p.trim()); - return placements; + return file.placements.split(",").map((p: string) => p.trim()); } return []; }); @@ -1122,8 +1143,7 @@ export default function FormTeksUpdate() { if (file.placements) { const placements = file.placements.split(",").map((p: string) => p.trim()); - - // Map dari format backend ke checkbox + if (placements.includes("all")) { selection.semua = true; selection.nasional = true; @@ -1132,23 +1152,21 @@ export default function FormTeksUpdate() { selection.polda = true; selection.satker = true; } else { - if (placements.includes("mabes")) { - selection.nasional = true; - } - if (placements.includes("wilayah")) { + if (placements.includes("mabes")) selection.nasional = true; + if (placements.includes("international")) selection.international = true; + if (placements.includes("polda")) selection.polda = true; + if (placements.includes("satker")) selection.satker = true; + // Wilayah aktif jika ada "wilayah" ATAU ada polda/satker + if ( + placements.includes("wilayah") || + placements.includes("polda") || + placements.includes("satker") + ) { selection.wilayah = true; } - if (placements.includes("polda")) { - selection.polda = true; - } - if (placements.includes("satker")) { - selection.satker = true; - } - if (placements.includes("international")) { - selection.international = true; - } } } + return selection; }); setFileUnitSelections(initialFileUnitSelections); @@ -1240,6 +1258,16 @@ export default function FormTeksUpdate() { setIsStartUpload(true); setProgressList(progressInfoArr); + // Update file placements terlebih dahulu (sebelum upload) + const placementData = getPlacement(); + if (placementData.length > 0) { + const responseFilePlacements = await updateFilePlacements(placementData); + if (responseFilePlacements?.error) { + error(responseFilePlacements?.message); + return false; + } + } + close(); // showProgress(); files.map(async (item: any, index: number) => { @@ -1251,12 +1279,6 @@ export default function FormTeksUpdate() { ); }); - // Update file placements - const placementData = getPlacement(); - if (placementData.length > 0) { - await updateFilePlacements(placementData); - } - MySwal.fire({ title: "Sukses", text: "Data berhasil disimpan.", @@ -1594,13 +1616,13 @@ export default function FormTeksUpdate() { ) : null} {files.length > 0 && ( -
-