Merge branch 'main' of https://gitlab.com/hanifsalafi/mediahub_redesign into prod
This commit is contained in:
commit
ca5a150015
|
|
@ -101,10 +101,8 @@ const useTableColumns = () => {
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const levelNumber = Number(getCookiesDecrypt("ulne")); // 1 = Mabes, 2 = Polda
|
const levelNumber = Number(getCookiesDecrypt("ulne"));
|
||||||
const calendarOwnerLevel = Number(row.original.assignedToLevel); // dari API
|
const userId = Number(getCookiesDecrypt("uie"));
|
||||||
const calendarOwner = row.original.assignedTo; // ID unit Polda/Mabes dari API
|
|
||||||
const myUnit = getCookiesDecrypt("unitId"); // misal ID unit Polda login
|
|
||||||
|
|
||||||
async function doDelete(id: any) {
|
async function doDelete(id: any) {
|
||||||
const response = await deleteCalendar(id);
|
const response = await deleteCalendar(id);
|
||||||
|
|
@ -143,29 +141,6 @@ const useTableColumns = () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// === RULE AKSI ===
|
|
||||||
let canEdit = false;
|
|
||||||
let canDelete = false;
|
|
||||||
const canView = true;
|
|
||||||
|
|
||||||
if (levelNumber === 1) {
|
|
||||||
// Mabes -> bebas
|
|
||||||
canEdit = true;
|
|
||||||
canDelete = true;
|
|
||||||
} else if (levelNumber === 2) {
|
|
||||||
// Polda
|
|
||||||
if (calendarOwnerLevel === 1) {
|
|
||||||
// kalender Mabes -> hanya view
|
|
||||||
canEdit = false;
|
|
||||||
canDelete = false;
|
|
||||||
} else if (calendarOwnerLevel === 2 && calendarOwner === myUnit) {
|
|
||||||
// kalender polda sendiri -> bisa edit/delete
|
|
||||||
canEdit = true;
|
|
||||||
canDelete = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
|
|
@ -178,7 +153,7 @@ const useTableColumns = () => {
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<DropdownMenuContent className="p-0" align="end">
|
||||||
{canView && (
|
|
||||||
<Link
|
<Link
|
||||||
href={`/contributor/schedule/calendar-polri/detail/${row.original.id}`}
|
href={`/contributor/schedule/calendar-polri/detail/${row.original.id}`}
|
||||||
>
|
>
|
||||||
|
|
@ -187,9 +162,9 @@ const useTableColumns = () => {
|
||||||
Detail
|
Detail
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
|
||||||
|
|
||||||
{canEdit && (
|
|
||||||
|
{row.original.createdById === userId && (
|
||||||
<Link
|
<Link
|
||||||
href={`/contributor/schedule/calendar-polri/update/${row.original.id}`}
|
href={`/contributor/schedule/calendar-polri/update/${row.original.id}`}
|
||||||
>
|
>
|
||||||
|
|
@ -200,7 +175,7 @@ const useTableColumns = () => {
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{canDelete && (
|
{row.original.createdById === userId && (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => handleDeleteCalendars(row.original.id)}
|
onClick={() => handleDeleteCalendars(row.original.id)}
|
||||||
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import { Reveal } from "@/components/landing-page/Reveal";
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
interface FAQItem {
|
interface FAQItem {
|
||||||
question: string;
|
question: string;
|
||||||
|
|
@ -41,19 +42,41 @@ const FAQS: React.FC = () => {
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<div className="flex items-center justify-center mb-6">
|
<div className="flex items-center justify-center mb-6">
|
||||||
<img src="/assets/icons-faqs.png" alt="Faqs" />
|
<Image
|
||||||
<h2 className="ml-4 text-lg lg:text-2xl font-bold text-gray-800 dark:text-white">Frequently Asked Questions</h2>
|
width={1920}
|
||||||
|
height={1080}
|
||||||
|
src="/assets/icons-faqs.png"
|
||||||
|
alt="Faqs"
|
||||||
|
className="h-12 w-12"
|
||||||
|
/>
|
||||||
|
<h2 className="ml-4 text-lg lg:text-2xl font-bold text-gray-800 dark:text-white">
|
||||||
|
Frequently Asked Questions
|
||||||
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* FAQS Items */}
|
{/* FAQS Items */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{faqs?.map((faq, index) => (
|
{faqs?.map((faq, index) => (
|
||||||
<div key={index} className="border-b border-gray-300 pb-2 cursor-pointer">
|
<div
|
||||||
<div className="flex justify-between items-center" onClick={() => toggleFAQ(index)}>
|
key={index}
|
||||||
<h3 className="text-sm font-semibold text-gray-800 dark:text-white">{faq.question}</h3>
|
className="border-b border-gray-300 pb-2 cursor-pointer"
|
||||||
<span className="text-gray-500 dark:text-white text-xl">{openIndex === index ? "−" : "+"}</span>
|
>
|
||||||
|
<div
|
||||||
|
className="flex justify-between items-center"
|
||||||
|
onClick={() => toggleFAQ(index)}
|
||||||
|
>
|
||||||
|
<h3 className="text-sm font-semibold text-gray-800 dark:text-white">
|
||||||
|
{faq.question}
|
||||||
|
</h3>
|
||||||
|
<span className="text-gray-500 dark:text-white text-xl">
|
||||||
|
{openIndex === index ? "−" : "+"}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{openIndex === index && <p className="text-gray-600 dark:text-white mt-2 text-sm">{faq.answer}</p>}
|
{openIndex === index && (
|
||||||
|
<p className="text-gray-600 dark:text-white mt-2 text-sm">
|
||||||
|
{faq.answer}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ import {
|
||||||
saveMediaBlastCampaign,
|
saveMediaBlastCampaign,
|
||||||
} from "@/service/broadcast/broadcast";
|
} from "@/service/broadcast/broadcast";
|
||||||
import { error } from "@/config/swal";
|
import { error } from "@/config/swal";
|
||||||
import { useRouter } from "@/i18n/routing";
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
|
|
@ -78,6 +78,11 @@ const FormSchema = z.object({
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
interface Campaign {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default function ContentBlast(props: { type: string }) {
|
export default function ContentBlast(props: { type: string }) {
|
||||||
const editor = useRef(null);
|
const editor = useRef(null);
|
||||||
const id = useParams()?.id;
|
const id = useParams()?.id;
|
||||||
|
|
@ -85,7 +90,7 @@ export default function ContentBlast(props: { type: string }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { type } = props;
|
const { type } = props;
|
||||||
|
|
||||||
const [dataSelectCampaign, setDataSelectCampaign] = useState([]);
|
const [dataSelectCampaign, setDataSelectCampaign] = useState<Campaign[]>([]);
|
||||||
const [openModal, setOpenModal] = useState(false);
|
const [openModal, setOpenModal] = useState(false);
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof FormSchema>>({
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
|
|
@ -295,9 +300,16 @@ export default function ContentBlast(props: { type: string }) {
|
||||||
Untuk melihat Email Terkirim silahkan cek menu “Sent”!
|
Untuk melihat Email Terkirim silahkan cek menu “Sent”!
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter className="flex justify-center">
|
<DialogFooter className="flex justify-center">
|
||||||
|
<Link
|
||||||
|
href={`/admin/broadcast/campaign-list/detail/${
|
||||||
|
form.getValues("selected")[0]?.id
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<Button type="button" color="success">
|
<Button type="button" color="success">
|
||||||
Menu "Sent"
|
Menu "Sent"
|
||||||
</Button>
|
</Button>
|
||||||
|
</Link>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => router.push("/admin/broadcast")}
|
onClick={() => router.push("/admin/broadcast")}
|
||||||
|
|
|
||||||
|
|
@ -200,6 +200,12 @@ export default function FormAudioDetail() {
|
||||||
}>
|
}>
|
||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
||||||
|
setIsUserMabesApprover(true);
|
||||||
|
}
|
||||||
|
}, [userLevelId, roleId]);
|
||||||
|
|
||||||
// Fungsi untuk mengupdate state individual file
|
// Fungsi untuk mengupdate state individual file
|
||||||
const handleFileUnitChange = (
|
const handleFileUnitChange = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
|
|
@ -219,6 +225,30 @@ export default function FormAudioDetail() {
|
||||||
currentSelection.polda = value;
|
currentSelection.polda = value;
|
||||||
currentSelection.polres = value;
|
currentSelection.polres = value;
|
||||||
currentSelection.satker = value;
|
currentSelection.satker = value;
|
||||||
|
|
||||||
|
// Update fileCheckedLevels untuk sinkronisasi dengan modal
|
||||||
|
setFileCheckedLevels((prevLevels) => {
|
||||||
|
const newArray = [...prevLevels];
|
||||||
|
const currentFileLevels = new Set<number>(newArray[fileIndex] || new Set());
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
// Checklist semua item di modal
|
||||||
|
listDest.forEach((item: any) => {
|
||||||
|
currentFileLevels.add(Number(item.id));
|
||||||
|
if (item.subDestination) {
|
||||||
|
item.subDestination.forEach((sub: any) => {
|
||||||
|
currentFileLevels.add(Number(sub.id));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Unchecklist semua item di modal
|
||||||
|
currentFileLevels.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
newArray[fileIndex] = currentFileLevels;
|
||||||
|
return newArray;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist
|
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist
|
||||||
if (key === "polres" && value) {
|
if (key === "polres" && value) {
|
||||||
|
|
@ -480,10 +510,28 @@ export default function FormAudioDetail() {
|
||||||
|
|
||||||
const setupPlacementCheck = (length: number) => {
|
const setupPlacementCheck = (length: number) => {
|
||||||
const temp = [];
|
const temp = [];
|
||||||
|
const unitSelections = [];
|
||||||
|
const checkedLevelsArray = [];
|
||||||
|
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
temp.push([]);
|
temp.push([]);
|
||||||
|
// Inisialisasi state untuk setiap file
|
||||||
|
unitSelections.push({
|
||||||
|
semua: false,
|
||||||
|
nasional: false,
|
||||||
|
wilayah: false,
|
||||||
|
international: false,
|
||||||
|
polda: false,
|
||||||
|
polres: false,
|
||||||
|
satker: false,
|
||||||
|
});
|
||||||
|
// Inisialisasi checkedLevels untuk setiap file
|
||||||
|
checkedLevelsArray.push(new Set<number>());
|
||||||
}
|
}
|
||||||
|
|
||||||
setFilePlacements(temp);
|
setFilePlacements(temp);
|
||||||
|
setFileUnitSelections(unitSelections);
|
||||||
|
setFileCheckedLevels(checkedLevelsArray);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -587,8 +635,24 @@ export default function FormAudioDetail() {
|
||||||
const temp = [];
|
const temp = [];
|
||||||
for (let i = 0; i < filePlacements?.length; i++) {
|
for (let i = 0; i < filePlacements?.length; i++) {
|
||||||
if (filePlacements[i]?.length !== 0) {
|
if (filePlacements[i]?.length !== 0) {
|
||||||
const now = filePlacements[i]?.filter((a) => a !== "all");
|
// const now = filePlacements[i]?.filter((a) => a !== "all");
|
||||||
const data = { mediaFileId: files[i]?.id, placements: now.join(",") };
|
// const data = { mediaFileId: files[i]?.id, placements: now.join(",") };
|
||||||
|
const now = filePlacements[i];
|
||||||
|
let nowArr = now?.join(",")?.replaceAll("wilayah", "polda");
|
||||||
|
nowArr = nowArr?.replaceAll("nasional", "mabes");
|
||||||
|
nowArr = nowArr?.replaceAll("semua", "all");
|
||||||
|
|
||||||
|
// Dapatkan checked levels untuk file ini
|
||||||
|
const currentFileCheckedLevels = fileCheckedLevels[i]
|
||||||
|
? Array.from(fileCheckedLevels[i])
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
mediaFileId: files[i]?.id,
|
||||||
|
placements: nowArr,
|
||||||
|
customLocationPlacements: currentFileCheckedLevels.join(","),
|
||||||
|
};
|
||||||
|
|
||||||
temp.push(data);
|
temp.push(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -596,13 +660,19 @@ export default function FormAudioDetail() {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
|
// Gabungkan semua checkedLevels dari semua file
|
||||||
|
const allCheckedLevels = new Set<number>();
|
||||||
|
fileCheckedLevels.forEach((fileLevels) => {
|
||||||
|
fileLevels.forEach((levelId) => {
|
||||||
|
allCheckedLevels.add(levelId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
mediaUploadId: id,
|
mediaUploadId: id,
|
||||||
statusId: status,
|
statusId: status,
|
||||||
message: description,
|
message: description,
|
||||||
// files: [],
|
|
||||||
files: isUserMabesApprover ? getPlacement() : [],
|
files: isUserMabesApprover ? getPlacement() : [],
|
||||||
customLocationPlacement: Array.from(checkedLevels).join(","),
|
|
||||||
};
|
};
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
loading();
|
loading();
|
||||||
|
|
@ -638,37 +708,129 @@ export default function FormAudioDetail() {
|
||||||
setRejectedFiles(rejects);
|
setRejectedFiles(rejects);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
// if (placement === "all") {
|
if (placement === "all") {
|
||||||
// temp[index] = ["all", "mabes", "polda", "international"];
|
temp[index] = ["all", "mabes", "polda", "international"];
|
||||||
// } else {
|
|
||||||
// const now = temp[index];
|
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik
|
||||||
// now?.push(placement);
|
setFileCheckedLevels((prevLevels) => {
|
||||||
// if (now?.length === 3 && !now?.includes("all")) {
|
const newArray = [...prevLevels];
|
||||||
// now?.push("all");
|
const currentFileLevels = new Set<number>(newArray[index] || new Set());
|
||||||
// }
|
|
||||||
// temp[index] = now;
|
// Checklist semua item di modal
|
||||||
// }
|
listDest.forEach((item: any) => {
|
||||||
// } else {
|
currentFileLevels.add(Number(item.id));
|
||||||
// if (placement === "all") {
|
if (item.subDestination) {
|
||||||
// temp[index] = [];
|
item.subDestination.forEach((sub: any) => {
|
||||||
// } else {
|
currentFileLevels.add(Number(sub.id));
|
||||||
// const now = temp[index].filter((a) => a !== placement);
|
});
|
||||||
// temp[index] = now;
|
}
|
||||||
// if (now?.length === 3 && now?.includes("all")) {
|
});
|
||||||
// const newData = now.filter((b) => b !== "all");
|
|
||||||
// temp[index] = newData;
|
newArray[index] = currentFileLevels;
|
||||||
// }
|
return newArray;
|
||||||
// }
|
});
|
||||||
// }
|
|
||||||
// setFilePlacements(temp);
|
// Update fileUnitSelections untuk checkbox tingkat utama
|
||||||
// };
|
setFileUnitSelections((prevSelections) => {
|
||||||
|
const newSelections = [...prevSelections];
|
||||||
|
const currentSelection = { ...newSelections[index] };
|
||||||
|
|
||||||
|
// Set semua checkbox tingkat utama ke true
|
||||||
|
currentSelection.nasional = true;
|
||||||
|
currentSelection.wilayah = true;
|
||||||
|
currentSelection.international = true;
|
||||||
|
currentSelection.polda = true;
|
||||||
|
currentSelection.polres = true;
|
||||||
|
currentSelection.satker = true;
|
||||||
|
currentSelection.semua = true;
|
||||||
|
|
||||||
|
newSelections[index] = currentSelection;
|
||||||
|
return newSelections;
|
||||||
|
});
|
||||||
|
} else if (placement === "satker") {
|
||||||
|
// Ketika satker di-checklist, HANYA tambahkan satker saja
|
||||||
|
// JANGAN otomatis checklist polres
|
||||||
|
const now = temp[index] || [];
|
||||||
|
if (!now.includes("satker")) {
|
||||||
|
now.push("satker");
|
||||||
|
}
|
||||||
|
temp[index] = now;
|
||||||
|
} else {
|
||||||
|
const now = temp[index] || [];
|
||||||
|
if (!now.includes(placement)) {
|
||||||
|
now.push(placement);
|
||||||
|
}
|
||||||
|
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
||||||
|
// JANGAN include satker dalam perhitungan auto "all"
|
||||||
|
const nonSatkerItems = now.filter(
|
||||||
|
(item) => item !== "satker" && item !== "all"
|
||||||
|
);
|
||||||
|
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
||||||
|
now.push("all");
|
||||||
|
}
|
||||||
|
temp[index] = now;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (placement === "all") {
|
||||||
|
temp[index] = [];
|
||||||
|
|
||||||
|
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" di-unchecklist
|
||||||
|
setFileCheckedLevels((prevLevels) => {
|
||||||
|
const newArray = [...prevLevels];
|
||||||
|
const currentFileLevels = new Set<number>(newArray[index] || new Set());
|
||||||
|
|
||||||
|
// Unchecklist semua item di modal
|
||||||
|
currentFileLevels.clear();
|
||||||
|
|
||||||
|
newArray[index] = currentFileLevels;
|
||||||
|
return newArray;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update fileUnitSelections untuk checkbox tingkat utama
|
||||||
|
setFileUnitSelections((prevSelections) => {
|
||||||
|
const newSelections = [...prevSelections];
|
||||||
|
const currentSelection = { ...newSelections[index] };
|
||||||
|
|
||||||
|
// Set semua checkbox tingkat utama ke false
|
||||||
|
currentSelection.nasional = false;
|
||||||
|
currentSelection.wilayah = false;
|
||||||
|
currentSelection.international = false;
|
||||||
|
currentSelection.polda = false;
|
||||||
|
currentSelection.polres = false;
|
||||||
|
currentSelection.satker = false;
|
||||||
|
currentSelection.semua = false;
|
||||||
|
|
||||||
|
newSelections[index] = currentSelection;
|
||||||
|
return newSelections;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const now = temp[index]?.filter((a) => a !== placement);
|
||||||
|
console.log("now", now);
|
||||||
|
temp[index] = now;
|
||||||
|
// Hapus "all" jika tidak semua item ter-checklist
|
||||||
|
if (now.includes("all")) {
|
||||||
|
const nonSatkerItems = now.filter(
|
||||||
|
(item) => item !== "satker" && item !== "all"
|
||||||
|
);
|
||||||
|
if (nonSatkerItems.length < 3) {
|
||||||
|
const newData = now.filter((b) => b !== "all");
|
||||||
|
temp[index] = newData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setFilePlacements(temp);
|
||||||
|
|
||||||
|
// Update checklist levels di modal berdasarkan placement yang diubah
|
||||||
|
updateModalChecklistLevels(index, placement, checked);
|
||||||
|
};
|
||||||
|
|
||||||
const handleMain = (
|
const handleMain = (
|
||||||
type: string,
|
type: string,
|
||||||
|
|
@ -706,62 +868,7 @@ export default function FormAudioDetail() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const setupPlacement = (
|
|
||||||
index: number,
|
|
||||||
placement: string,
|
|
||||||
checked: boolean
|
|
||||||
) => {
|
|
||||||
let temp = [...filePlacements];
|
|
||||||
if (checked) {
|
|
||||||
if (placement === "all") {
|
|
||||||
temp[index] = ["all", "mabes", "polda", "international"];
|
|
||||||
} else if (placement === "satker") {
|
|
||||||
// Ketika satker di-checklist, HANYA tambahkan satker saja
|
|
||||||
// JANGAN otomatis checklist polres
|
|
||||||
const now = temp[index] || [];
|
|
||||||
if (!now.includes("satker")) {
|
|
||||||
now.push("satker");
|
|
||||||
}
|
|
||||||
temp[index] = now;
|
|
||||||
} else {
|
|
||||||
const now = temp[index] || [];
|
|
||||||
if (!now.includes(placement)) {
|
|
||||||
now.push(placement);
|
|
||||||
}
|
|
||||||
// Hanya auto-checklist "all" jika polda, polres, dan mabes ter-checklist
|
|
||||||
// JANGAN include satker dalam perhitungan auto "all"
|
|
||||||
const nonSatkerItems = now.filter(
|
|
||||||
(item) => item !== "satker" && item !== "all"
|
|
||||||
);
|
|
||||||
if (nonSatkerItems.length === 3 && !now.includes("all")) {
|
|
||||||
now.push("all");
|
|
||||||
}
|
|
||||||
temp[index] = now;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (placement === "all") {
|
|
||||||
temp[index] = [];
|
|
||||||
} else {
|
|
||||||
const now = temp[index]?.filter((a) => a !== placement);
|
|
||||||
console.log("now", now);
|
|
||||||
temp[index] = now;
|
|
||||||
// Hapus "all" jika tidak semua item ter-checklist
|
|
||||||
if (now.includes("all")) {
|
|
||||||
const nonSatkerItems = now.filter(
|
|
||||||
(item) => item !== "satker" && item !== "all"
|
|
||||||
);
|
|
||||||
if (nonSatkerItems.length < 3) {
|
|
||||||
const newData = now.filter((b) => b !== "all");
|
|
||||||
temp[index] = newData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setFilePlacements(temp);
|
|
||||||
|
|
||||||
// Update checklist levels di modal berdasarkan placement yang diubah
|
|
||||||
updateModalChecklistLevels(index, placement, checked);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateModalChecklistLevels = (
|
const updateModalChecklistLevels = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
|
|
@ -992,6 +1099,15 @@ export default function FormAudioDetail() {
|
||||||
currentSelection.polres = checkedPolresCount > 0;
|
currentSelection.polres = checkedPolresCount > 0;
|
||||||
currentSelection.satker = Boolean(isSatkerChecked);
|
currentSelection.satker = Boolean(isSatkerChecked);
|
||||||
|
|
||||||
|
// Update checkbox "semua" berdasarkan semua checkbox yang aktif
|
||||||
|
currentSelection.semua =
|
||||||
|
currentSelection.nasional &&
|
||||||
|
currentSelection.wilayah &&
|
||||||
|
currentSelection.international &&
|
||||||
|
currentSelection.polda &&
|
||||||
|
currentSelection.polres &&
|
||||||
|
currentSelection.satker;
|
||||||
|
|
||||||
newSelections[fileIndex] = currentSelection;
|
newSelections[fileIndex] = currentSelection;
|
||||||
return newSelections;
|
return newSelections;
|
||||||
});
|
});
|
||||||
|
|
@ -1303,6 +1419,13 @@ export default function FormAudioDetail() {
|
||||||
<p className="text-sm text-gray-600 break-all">
|
<p className="text-sm text-gray-600 break-all">
|
||||||
{file.fileName}
|
{file.fileName}
|
||||||
</p>
|
</p>
|
||||||
|
{isUserMabesApprover ? (
|
||||||
|
""
|
||||||
|
) : (
|
||||||
|
<p className="status text-success text-sm mb-0">
|
||||||
|
Selesai
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
|
@ -1320,6 +1443,7 @@ export default function FormAudioDetail() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Section Pengaturan Distribusi */}
|
{/* Section Pengaturan Distribusi */}
|
||||||
|
{isUserMabesApprover ? (
|
||||||
<div className="bg-white rounded-md p-4 border">
|
<div className="bg-white rounded-md p-4 border">
|
||||||
<h5 className="font-medium text-gray-900 mb-4 flex items-center gap-2">
|
<h5 className="font-medium text-gray-900 mb-4 flex items-center gap-2">
|
||||||
<Icon
|
<Icon
|
||||||
|
|
@ -1486,7 +1610,9 @@ export default function FormAudioDetail() {
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
toggleExpand(polda.id);
|
toggleExpand(
|
||||||
|
polda.id
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
className="p-1 hover:bg-gray-100 rounded-md transition-colors"
|
className="p-1 hover:bg-gray-100 rounded-md transition-colors"
|
||||||
>
|
>
|
||||||
|
|
@ -1518,7 +1644,9 @@ export default function FormAudioDetail() {
|
||||||
fileCheckedLevels[
|
fileCheckedLevels[
|
||||||
index
|
index
|
||||||
]?.has(
|
]?.has(
|
||||||
Number(sub.id)
|
Number(
|
||||||
|
sub.id
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
@ -1538,7 +1666,9 @@ export default function FormAudioDetail() {
|
||||||
<Icon
|
<Icon
|
||||||
icon="material-symbols:check-indeterminate-small"
|
icon="material-symbols:check-indeterminate-small"
|
||||||
width={12}
|
width={12}
|
||||||
height={12}
|
height={
|
||||||
|
12
|
||||||
|
}
|
||||||
className="mr-1"
|
className="mr-1"
|
||||||
/>
|
/>
|
||||||
Batal Semua
|
Batal Semua
|
||||||
|
|
@ -1548,7 +1678,9 @@ export default function FormAudioDetail() {
|
||||||
<Icon
|
<Icon
|
||||||
icon="material-symbols:check-all"
|
icon="material-symbols:check-all"
|
||||||
width={12}
|
width={12}
|
||||||
height={12}
|
height={
|
||||||
|
12
|
||||||
|
}
|
||||||
className="mr-1"
|
className="mr-1"
|
||||||
/>
|
/>
|
||||||
Pilih Semua
|
Pilih Semua
|
||||||
|
|
@ -1606,9 +1738,10 @@ export default function FormAudioDetail() {
|
||||||
</DialogClose>
|
</DialogClose>
|
||||||
<DialogClose asChild>
|
<DialogClose asChild>
|
||||||
<Button>
|
<Button>
|
||||||
{t("save", {
|
{/* {t("save", {
|
||||||
defaultValue: "Simpan",
|
defaultValue: "Simpan",
|
||||||
})}
|
})} */}
|
||||||
|
Simpan
|
||||||
</Button>
|
</Button>
|
||||||
</DialogClose>
|
</DialogClose>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1620,6 +1753,9 @@ export default function FormAudioDetail() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -189,6 +189,12 @@ export default function FormTeksDetail() {
|
||||||
}>
|
}>
|
||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
||||||
|
setIsUserMabesApprover(true);
|
||||||
|
}
|
||||||
|
}, [userLevelId, roleId]);
|
||||||
|
|
||||||
// Fungsi untuk mengupdate state individual file
|
// Fungsi untuk mengupdate state individual file
|
||||||
const handleFileUnitChange = (
|
const handleFileUnitChange = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
|
|
@ -208,6 +214,30 @@ export default function FormTeksDetail() {
|
||||||
currentSelection.polda = value;
|
currentSelection.polda = value;
|
||||||
currentSelection.polres = value;
|
currentSelection.polres = value;
|
||||||
currentSelection.satker = value;
|
currentSelection.satker = value;
|
||||||
|
|
||||||
|
// Update fileCheckedLevels untuk sinkronisasi dengan modal
|
||||||
|
setFileCheckedLevels((prevLevels) => {
|
||||||
|
const newArray = [...prevLevels];
|
||||||
|
const currentFileLevels = new Set<number>(newArray[fileIndex] || new Set());
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
// Checklist semua item di modal
|
||||||
|
listDest.forEach((item: any) => {
|
||||||
|
currentFileLevels.add(Number(item.id));
|
||||||
|
if (item.subDestination) {
|
||||||
|
item.subDestination.forEach((sub: any) => {
|
||||||
|
currentFileLevels.add(Number(sub.id));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Unchecklist semua item di modal
|
||||||
|
currentFileLevels.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
newArray[fileIndex] = currentFileLevels;
|
||||||
|
return newArray;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist
|
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist
|
||||||
if (key === "polres" && value) {
|
if (key === "polres" && value) {
|
||||||
|
|
@ -440,10 +470,28 @@ export default function FormTeksDetail() {
|
||||||
|
|
||||||
const setupPlacementCheck = (length: number) => {
|
const setupPlacementCheck = (length: number) => {
|
||||||
const temp = [];
|
const temp = [];
|
||||||
|
const unitSelections = [];
|
||||||
|
const checkedLevelsArray = [];
|
||||||
|
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
temp.push([]);
|
temp.push([]);
|
||||||
|
// Inisialisasi state untuk setiap file
|
||||||
|
unitSelections.push({
|
||||||
|
semua: false,
|
||||||
|
nasional: false,
|
||||||
|
wilayah: false,
|
||||||
|
international: false,
|
||||||
|
polda: false,
|
||||||
|
polres: false,
|
||||||
|
satker: false,
|
||||||
|
});
|
||||||
|
// Inisialisasi checkedLevels untuk setiap file
|
||||||
|
checkedLevelsArray.push(new Set<number>());
|
||||||
}
|
}
|
||||||
|
|
||||||
setFilePlacements(temp);
|
setFilePlacements(temp);
|
||||||
|
setFileUnitSelections(unitSelections);
|
||||||
|
setFileCheckedLevels(checkedLevelsArray);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -460,6 +508,7 @@ export default function FormTeksDetail() {
|
||||||
names: details?.files[0]?.fileName,
|
names: details?.files[0]?.fileName,
|
||||||
format: details?.files[0]?.format,
|
format: details?.files[0]?.format,
|
||||||
});
|
});
|
||||||
|
setupPlacementCheck(details?.files?.length);
|
||||||
|
|
||||||
if (details?.assignedToLevel) {
|
if (details?.assignedToLevel) {
|
||||||
const levels = new Set(
|
const levels = new Set(
|
||||||
|
|
@ -530,12 +579,27 @@ export default function FormTeksDetail() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPlacement = () => {
|
const getPlacement = () => {
|
||||||
// console.log("getPlaa", filePlacements);
|
|
||||||
const temp = [];
|
const temp = [];
|
||||||
for (let i = 0; i < filePlacements?.length; i++) {
|
for (let i = 0; i < filePlacements?.length; i++) {
|
||||||
if (filePlacements[i]?.length !== 0) {
|
if (filePlacements[i]?.length !== 0) {
|
||||||
const now = filePlacements[i]?.filter((a) => a !== "all");
|
// const now = filePlacements[i]?.filter((a) => a !== "all");
|
||||||
const data = { mediaFileId: files[i]?.id, placements: now?.join(",") };
|
// const data = { mediaFileId: files[i]?.id, placements: now?.join(",") };
|
||||||
|
const now = filePlacements[i];
|
||||||
|
let nowArr = now?.join(",")?.replaceAll("wilayah", "polda");
|
||||||
|
nowArr = nowArr?.replaceAll("nasional", "mabes");
|
||||||
|
nowArr = nowArr?.replaceAll("semua", "all");
|
||||||
|
|
||||||
|
// Dapatkan checked levels untuk file ini
|
||||||
|
const currentFileCheckedLevels = fileCheckedLevels[i]
|
||||||
|
? Array.from(fileCheckedLevels[i])
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
mediaFileId: files[i]?.id,
|
||||||
|
placements: nowArr,
|
||||||
|
customLocationPlacements: currentFileCheckedLevels.join(","),
|
||||||
|
};
|
||||||
|
|
||||||
temp.push(data);
|
temp.push(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -543,12 +607,19 @@ export default function FormTeksDetail() {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
|
// Gabungkan semua checkedLevels dari semua file
|
||||||
|
const allCheckedLevels = new Set<number>();
|
||||||
|
fileCheckedLevels.forEach((fileLevels) => {
|
||||||
|
fileLevels.forEach((levelId) => {
|
||||||
|
allCheckedLevels.add(levelId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
mediaUploadId: id,
|
mediaUploadId: id,
|
||||||
statusId: status,
|
statusId: status,
|
||||||
message: description,
|
message: description,
|
||||||
files: isUserMabesApprover ? getPlacement() : [],
|
files: isUserMabesApprover ? getPlacement() : [],
|
||||||
customLocationPlacement: Array.from(checkedLevels).join(","),
|
|
||||||
};
|
};
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
|
|
||||||
|
|
@ -653,6 +724,43 @@ export default function FormTeksDetail() {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
if (placement === "all") {
|
if (placement === "all") {
|
||||||
temp[index] = ["all", "mabes", "polda", "international"];
|
temp[index] = ["all", "mabes", "polda", "international"];
|
||||||
|
|
||||||
|
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik
|
||||||
|
setFileCheckedLevels((prevLevels) => {
|
||||||
|
const newArray = [...prevLevels];
|
||||||
|
const currentFileLevels = new Set<number>(newArray[index] || new Set());
|
||||||
|
|
||||||
|
// Checklist semua item di modal
|
||||||
|
listDest.forEach((item: any) => {
|
||||||
|
currentFileLevels.add(Number(item.id));
|
||||||
|
if (item.subDestination) {
|
||||||
|
item.subDestination.forEach((sub: any) => {
|
||||||
|
currentFileLevels.add(Number(sub.id));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
newArray[index] = currentFileLevels;
|
||||||
|
return newArray;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update fileUnitSelections untuk checkbox tingkat utama
|
||||||
|
setFileUnitSelections((prevSelections) => {
|
||||||
|
const newSelections = [...prevSelections];
|
||||||
|
const currentSelection = { ...newSelections[index] };
|
||||||
|
|
||||||
|
// Set semua checkbox tingkat utama ke true
|
||||||
|
currentSelection.nasional = true;
|
||||||
|
currentSelection.wilayah = true;
|
||||||
|
currentSelection.international = true;
|
||||||
|
currentSelection.polda = true;
|
||||||
|
currentSelection.polres = true;
|
||||||
|
currentSelection.satker = true;
|
||||||
|
currentSelection.semua = true;
|
||||||
|
|
||||||
|
newSelections[index] = currentSelection;
|
||||||
|
return newSelections;
|
||||||
|
});
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Ketika satker di-checklist, HANYA tambahkan satker saja
|
// Ketika satker di-checklist, HANYA tambahkan satker saja
|
||||||
// JANGAN otomatis checklist polres
|
// JANGAN otomatis checklist polres
|
||||||
|
|
@ -679,6 +787,36 @@ export default function FormTeksDetail() {
|
||||||
} else {
|
} else {
|
||||||
if (placement === "all") {
|
if (placement === "all") {
|
||||||
temp[index] = [];
|
temp[index] = [];
|
||||||
|
|
||||||
|
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" di-unchecklist
|
||||||
|
setFileCheckedLevels((prevLevels) => {
|
||||||
|
const newArray = [...prevLevels];
|
||||||
|
const currentFileLevels = new Set<number>(newArray[index] || new Set());
|
||||||
|
|
||||||
|
// Unchecklist semua item di modal
|
||||||
|
currentFileLevels.clear();
|
||||||
|
|
||||||
|
newArray[index] = currentFileLevels;
|
||||||
|
return newArray;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update fileUnitSelections untuk checkbox tingkat utama
|
||||||
|
setFileUnitSelections((prevSelections) => {
|
||||||
|
const newSelections = [...prevSelections];
|
||||||
|
const currentSelection = { ...newSelections[index] };
|
||||||
|
|
||||||
|
// Set semua checkbox tingkat utama ke false
|
||||||
|
currentSelection.nasional = false;
|
||||||
|
currentSelection.wilayah = false;
|
||||||
|
currentSelection.international = false;
|
||||||
|
currentSelection.polda = false;
|
||||||
|
currentSelection.polres = false;
|
||||||
|
currentSelection.satker = false;
|
||||||
|
currentSelection.semua = false;
|
||||||
|
|
||||||
|
newSelections[index] = currentSelection;
|
||||||
|
return newSelections;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const now = temp[index]?.filter((a) => a !== placement);
|
const now = temp[index]?.filter((a) => a !== placement);
|
||||||
console.log("now", now);
|
console.log("now", now);
|
||||||
|
|
@ -930,6 +1068,15 @@ export default function FormTeksDetail() {
|
||||||
currentSelection.polres = checkedPolresCount > 0;
|
currentSelection.polres = checkedPolresCount > 0;
|
||||||
currentSelection.satker = Boolean(isSatkerChecked);
|
currentSelection.satker = Boolean(isSatkerChecked);
|
||||||
|
|
||||||
|
// Update checkbox "semua" berdasarkan semua checkbox yang aktif
|
||||||
|
currentSelection.semua =
|
||||||
|
currentSelection.nasional &&
|
||||||
|
currentSelection.wilayah &&
|
||||||
|
currentSelection.international &&
|
||||||
|
currentSelection.polda &&
|
||||||
|
currentSelection.polres &&
|
||||||
|
currentSelection.satker;
|
||||||
|
|
||||||
newSelections[fileIndex] = currentSelection;
|
newSelections[fileIndex] = currentSelection;
|
||||||
return newSelections;
|
return newSelections;
|
||||||
});
|
});
|
||||||
|
|
@ -1264,6 +1411,13 @@ export default function FormTeksDetail() {
|
||||||
<p className="text-sm text-gray-600 break-all">
|
<p className="text-sm text-gray-600 break-all">
|
||||||
{file.fileName}
|
{file.fileName}
|
||||||
</p>
|
</p>
|
||||||
|
{isUserMabesApprover ? (
|
||||||
|
""
|
||||||
|
) : (
|
||||||
|
<p className="status text-success text-sm mb-0">
|
||||||
|
Selesai
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
|
@ -1281,6 +1435,7 @@ export default function FormTeksDetail() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Section Pengaturan Distribusi */}
|
{/* Section Pengaturan Distribusi */}
|
||||||
|
{isUserMabesApprover ? (
|
||||||
<div className="bg-white rounded-md p-4 border">
|
<div className="bg-white rounded-md p-4 border">
|
||||||
<h5 className="font-medium text-gray-900 mb-4 flex items-center gap-2">
|
<h5 className="font-medium text-gray-900 mb-4 flex items-center gap-2">
|
||||||
<Icon
|
<Icon
|
||||||
|
|
@ -1447,7 +1602,9 @@ export default function FormTeksDetail() {
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
toggleExpand(polda.id);
|
toggleExpand(
|
||||||
|
polda.id
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
className="p-1 hover:bg-gray-100 rounded-md transition-colors"
|
className="p-1 hover:bg-gray-100 rounded-md transition-colors"
|
||||||
>
|
>
|
||||||
|
|
@ -1479,7 +1636,9 @@ export default function FormTeksDetail() {
|
||||||
fileCheckedLevels[
|
fileCheckedLevels[
|
||||||
index
|
index
|
||||||
]?.has(
|
]?.has(
|
||||||
Number(sub.id)
|
Number(
|
||||||
|
sub.id
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
@ -1499,7 +1658,9 @@ export default function FormTeksDetail() {
|
||||||
<Icon
|
<Icon
|
||||||
icon="material-symbols:check-indeterminate-small"
|
icon="material-symbols:check-indeterminate-small"
|
||||||
width={12}
|
width={12}
|
||||||
height={12}
|
height={
|
||||||
|
12
|
||||||
|
}
|
||||||
className="mr-1"
|
className="mr-1"
|
||||||
/>
|
/>
|
||||||
Batal Semua
|
Batal Semua
|
||||||
|
|
@ -1509,7 +1670,9 @@ export default function FormTeksDetail() {
|
||||||
<Icon
|
<Icon
|
||||||
icon="material-symbols:check-all"
|
icon="material-symbols:check-all"
|
||||||
width={12}
|
width={12}
|
||||||
height={12}
|
height={
|
||||||
|
12
|
||||||
|
}
|
||||||
className="mr-1"
|
className="mr-1"
|
||||||
/>
|
/>
|
||||||
Pilih Semua
|
Pilih Semua
|
||||||
|
|
@ -1567,9 +1730,10 @@ export default function FormTeksDetail() {
|
||||||
</DialogClose>
|
</DialogClose>
|
||||||
<DialogClose asChild>
|
<DialogClose asChild>
|
||||||
<Button>
|
<Button>
|
||||||
{t("save", {
|
{/* {t("save", {
|
||||||
defaultValue: "Simpan",
|
defaultValue: "Simpan",
|
||||||
})}
|
})} */}
|
||||||
|
Simpan
|
||||||
</Button>
|
</Button>
|
||||||
</DialogClose>
|
</DialogClose>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1581,6 +1745,9 @@ export default function FormTeksDetail() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,12 @@ export default function FormVideoDetail() {
|
||||||
}>
|
}>
|
||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (Number(userLevelId) === 216 && Number(roleId) === 3) {
|
||||||
|
setIsUserMabesApprover(true);
|
||||||
|
}
|
||||||
|
}, [userLevelId, roleId]);
|
||||||
|
|
||||||
// Fungsi untuk mengupdate state individual file
|
// Fungsi untuk mengupdate state individual file
|
||||||
const handleFileUnitChange = (
|
const handleFileUnitChange = (
|
||||||
fileIndex: number,
|
fileIndex: number,
|
||||||
|
|
@ -211,6 +217,30 @@ export default function FormVideoDetail() {
|
||||||
currentSelection.polda = value;
|
currentSelection.polda = value;
|
||||||
currentSelection.polres = value;
|
currentSelection.polres = value;
|
||||||
currentSelection.satker = value;
|
currentSelection.satker = value;
|
||||||
|
|
||||||
|
// Update fileCheckedLevels untuk sinkronisasi dengan modal
|
||||||
|
setFileCheckedLevels((prevLevels) => {
|
||||||
|
const newArray = [...prevLevels];
|
||||||
|
const currentFileLevels = new Set<number>(newArray[fileIndex] || new Set());
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
// Checklist semua item di modal
|
||||||
|
listDest.forEach((item: any) => {
|
||||||
|
currentFileLevels.add(Number(item.id));
|
||||||
|
if (item.subDestination) {
|
||||||
|
item.subDestination.forEach((sub: any) => {
|
||||||
|
currentFileLevels.add(Number(sub.id));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Unchecklist semua item di modal
|
||||||
|
currentFileLevels.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
newArray[fileIndex] = currentFileLevels;
|
||||||
|
return newArray;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist
|
// Validasi khusus untuk POLRES - harus ada POLDA yang ter-checklist
|
||||||
if (key === "polres" && value) {
|
if (key === "polres" && value) {
|
||||||
|
|
@ -479,6 +509,31 @@ export default function FormVideoDetail() {
|
||||||
);
|
);
|
||||||
setDetailVideo(fileUrls);
|
setDetailVideo(fileUrls);
|
||||||
|
|
||||||
|
// Setup placement check untuk setiap file
|
||||||
|
const temp = [];
|
||||||
|
const unitSelections = [];
|
||||||
|
const checkedLevelsArray = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < details?.files?.length; i++) {
|
||||||
|
temp.push([]);
|
||||||
|
// Inisialisasi state untuk setiap file
|
||||||
|
unitSelections.push({
|
||||||
|
semua: false,
|
||||||
|
nasional: false,
|
||||||
|
wilayah: false,
|
||||||
|
international: false,
|
||||||
|
polda: false,
|
||||||
|
polres: false,
|
||||||
|
satker: false,
|
||||||
|
});
|
||||||
|
// Inisialisasi checkedLevels untuk setiap file
|
||||||
|
checkedLevelsArray.push(new Set<number>());
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilePlacements(temp);
|
||||||
|
setFileUnitSelections(unitSelections);
|
||||||
|
setFileCheckedLevels(checkedLevelsArray);
|
||||||
|
|
||||||
const approvals = await getDataApprovalByMediaUpload(details?.id);
|
const approvals = await getDataApprovalByMediaUpload(details?.id);
|
||||||
setApproval(approvals?.data?.data);
|
setApproval(approvals?.data?.data);
|
||||||
}
|
}
|
||||||
|
|
@ -523,12 +578,19 @@ export default function FormVideoDetail() {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
|
// Gabungkan semua checkedLevels dari semua file
|
||||||
|
const allCheckedLevels = new Set<number>();
|
||||||
|
fileCheckedLevels.forEach((fileLevels) => {
|
||||||
|
fileLevels.forEach((levelId) => {
|
||||||
|
allCheckedLevels.add(levelId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
mediaUploadId: id,
|
mediaUploadId: id,
|
||||||
statusId: status,
|
statusId: status,
|
||||||
message: description,
|
message: description,
|
||||||
files: isUserMabesApprover ? getPlacement() : [],
|
files: isUserMabesApprover ? getPlacement() : [],
|
||||||
customLocationPlacement: Array.from(checkedLevels).join(","),
|
|
||||||
};
|
};
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
loading();
|
loading();
|
||||||
|
|
@ -557,12 +619,28 @@ export default function FormVideoDetail() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPlacement = () => {
|
const getPlacement = () => {
|
||||||
// console.log("getPlaa", filePlacements);
|
|
||||||
const temp = [];
|
const temp = [];
|
||||||
for (let i = 0; i < filePlacements?.length; i++) {
|
for (let i = 0; i < filePlacements?.length; i++) {
|
||||||
if (filePlacements[i].length !== 0) {
|
if (filePlacements[i].length !== 0) {
|
||||||
const now = filePlacements[i].filter((a) => a !== "all");
|
// const now = filePlacements[i].filter((a) => a !== "all");
|
||||||
const data = { mediaFileId: files[i].id, placements: now.join(",") };
|
// const data = { mediaFileId: files[i].id, placements: now.join(",") };
|
||||||
|
// const now = filePlacements[i]?.filter((a) => a !== "semua");
|
||||||
|
const now = filePlacements[i];
|
||||||
|
let nowArr = now?.join(",")?.replaceAll("wilayah", "polda");
|
||||||
|
nowArr = nowArr?.replaceAll("nasional", "mabes");
|
||||||
|
nowArr = nowArr?.replaceAll("semua", "all");
|
||||||
|
|
||||||
|
// Dapatkan checked levels untuk file ini
|
||||||
|
const currentFileCheckedLevels = fileCheckedLevels[i]
|
||||||
|
? Array.from(fileCheckedLevels[i])
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
mediaFileId: files[i]?.id,
|
||||||
|
placements: nowArr,
|
||||||
|
customLocationPlacements: currentFileCheckedLevels.join(","),
|
||||||
|
};
|
||||||
|
|
||||||
temp.push(data);
|
temp.push(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -611,6 +689,43 @@ export default function FormVideoDetail() {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
if (placement === "all") {
|
if (placement === "all") {
|
||||||
temp[index] = ["all", "mabes", "polda", "international"];
|
temp[index] = ["all", "mabes", "polda", "international"];
|
||||||
|
|
||||||
|
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" diklik
|
||||||
|
setFileCheckedLevels((prevLevels) => {
|
||||||
|
const newArray = [...prevLevels];
|
||||||
|
const currentFileLevels = new Set<number>(newArray[index] || new Set());
|
||||||
|
|
||||||
|
// Checklist semua item di modal
|
||||||
|
listDest.forEach((item: any) => {
|
||||||
|
currentFileLevels.add(Number(item.id));
|
||||||
|
if (item.subDestination) {
|
||||||
|
item.subDestination.forEach((sub: any) => {
|
||||||
|
currentFileLevels.add(Number(sub.id));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
newArray[index] = currentFileLevels;
|
||||||
|
return newArray;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update fileUnitSelections untuk checkbox tingkat utama
|
||||||
|
setFileUnitSelections((prevSelections) => {
|
||||||
|
const newSelections = [...prevSelections];
|
||||||
|
const currentSelection = { ...newSelections[index] };
|
||||||
|
|
||||||
|
// Set semua checkbox tingkat utama ke true
|
||||||
|
currentSelection.nasional = true;
|
||||||
|
currentSelection.wilayah = true;
|
||||||
|
currentSelection.international = true;
|
||||||
|
currentSelection.polda = true;
|
||||||
|
currentSelection.polres = true;
|
||||||
|
currentSelection.satker = true;
|
||||||
|
currentSelection.semua = true;
|
||||||
|
|
||||||
|
newSelections[index] = currentSelection;
|
||||||
|
return newSelections;
|
||||||
|
});
|
||||||
} else if (placement === "satker") {
|
} else if (placement === "satker") {
|
||||||
// Ketika satker di-checklist, HANYA tambahkan satker saja
|
// Ketika satker di-checklist, HANYA tambahkan satker saja
|
||||||
// JANGAN otomatis checklist polres
|
// JANGAN otomatis checklist polres
|
||||||
|
|
@ -637,6 +752,36 @@ export default function FormVideoDetail() {
|
||||||
} else {
|
} else {
|
||||||
if (placement === "all") {
|
if (placement === "all") {
|
||||||
temp[index] = [];
|
temp[index] = [];
|
||||||
|
|
||||||
|
// Update fileCheckedLevels untuk sinkronisasi dengan modal ketika "all" di-unchecklist
|
||||||
|
setFileCheckedLevels((prevLevels) => {
|
||||||
|
const newArray = [...prevLevels];
|
||||||
|
const currentFileLevels = new Set<number>(newArray[index] || new Set());
|
||||||
|
|
||||||
|
// Unchecklist semua item di modal
|
||||||
|
currentFileLevels.clear();
|
||||||
|
|
||||||
|
newArray[index] = currentFileLevels;
|
||||||
|
return newArray;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update fileUnitSelections untuk checkbox tingkat utama
|
||||||
|
setFileUnitSelections((prevSelections) => {
|
||||||
|
const newSelections = [...prevSelections];
|
||||||
|
const currentSelection = { ...newSelections[index] };
|
||||||
|
|
||||||
|
// Set semua checkbox tingkat utama ke false
|
||||||
|
currentSelection.nasional = false;
|
||||||
|
currentSelection.wilayah = false;
|
||||||
|
currentSelection.international = false;
|
||||||
|
currentSelection.polda = false;
|
||||||
|
currentSelection.polres = false;
|
||||||
|
currentSelection.satker = false;
|
||||||
|
currentSelection.semua = false;
|
||||||
|
|
||||||
|
newSelections[index] = currentSelection;
|
||||||
|
return newSelections;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const now = temp[index].filter((a) => a !== placement);
|
const now = temp[index].filter((a) => a !== placement);
|
||||||
// console.log("now", now);
|
// console.log("now", now);
|
||||||
|
|
@ -925,6 +1070,15 @@ export default function FormVideoDetail() {
|
||||||
currentSelection.polres = checkedPolresCount > 0;
|
currentSelection.polres = checkedPolresCount > 0;
|
||||||
currentSelection.satker = Boolean(isSatkerChecked);
|
currentSelection.satker = Boolean(isSatkerChecked);
|
||||||
|
|
||||||
|
// Update checkbox "semua" berdasarkan semua checkbox yang aktif
|
||||||
|
currentSelection.semua =
|
||||||
|
currentSelection.nasional &&
|
||||||
|
currentSelection.wilayah &&
|
||||||
|
currentSelection.international &&
|
||||||
|
currentSelection.polda &&
|
||||||
|
currentSelection.polres &&
|
||||||
|
currentSelection.satker;
|
||||||
|
|
||||||
newSelections[fileIndex] = currentSelection;
|
newSelections[fileIndex] = currentSelection;
|
||||||
return newSelections;
|
return newSelections;
|
||||||
});
|
});
|
||||||
|
|
@ -1285,6 +1439,7 @@ export default function FormVideoDetail() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Section Pengaturan Distribusi */}
|
{/* Section Pengaturan Distribusi */}
|
||||||
|
{isUserMabesApprover ? (
|
||||||
<div className="bg-white rounded-md p-4 border">
|
<div className="bg-white rounded-md p-4 border">
|
||||||
<h5 className="font-medium text-gray-900 mb-4 flex items-center gap-2">
|
<h5 className="font-medium text-gray-900 mb-4 flex items-center gap-2">
|
||||||
<Icon
|
<Icon
|
||||||
|
|
@ -1451,7 +1606,9 @@ export default function FormVideoDetail() {
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
toggleExpand(polda.id);
|
toggleExpand(
|
||||||
|
polda.id
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
className="p-1 hover:bg-gray-100 rounded-md transition-colors"
|
className="p-1 hover:bg-gray-100 rounded-md transition-colors"
|
||||||
>
|
>
|
||||||
|
|
@ -1483,7 +1640,9 @@ export default function FormVideoDetail() {
|
||||||
fileCheckedLevels[
|
fileCheckedLevels[
|
||||||
index
|
index
|
||||||
]?.has(
|
]?.has(
|
||||||
Number(sub.id)
|
Number(
|
||||||
|
sub.id
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|
@ -1503,7 +1662,9 @@ export default function FormVideoDetail() {
|
||||||
<Icon
|
<Icon
|
||||||
icon="material-symbols:check-indeterminate-small"
|
icon="material-symbols:check-indeterminate-small"
|
||||||
width={12}
|
width={12}
|
||||||
height={12}
|
height={
|
||||||
|
12
|
||||||
|
}
|
||||||
className="mr-1"
|
className="mr-1"
|
||||||
/>
|
/>
|
||||||
Batal Semua
|
Batal Semua
|
||||||
|
|
@ -1513,7 +1674,9 @@ export default function FormVideoDetail() {
|
||||||
<Icon
|
<Icon
|
||||||
icon="material-symbols:check-all"
|
icon="material-symbols:check-all"
|
||||||
width={12}
|
width={12}
|
||||||
height={12}
|
height={
|
||||||
|
12
|
||||||
|
}
|
||||||
className="mr-1"
|
className="mr-1"
|
||||||
/>
|
/>
|
||||||
Pilih Semua
|
Pilih Semua
|
||||||
|
|
@ -1571,9 +1734,10 @@ export default function FormVideoDetail() {
|
||||||
</DialogClose>
|
</DialogClose>
|
||||||
<DialogClose asChild>
|
<DialogClose asChild>
|
||||||
<Button>
|
<Button>
|
||||||
{t("save", {
|
{/* {t("save", {
|
||||||
defaultValue: "Simpan",
|
defaultValue: "Simpan",
|
||||||
})}
|
})} */}
|
||||||
|
Simpan
|
||||||
</Button>
|
</Button>
|
||||||
</DialogClose>
|
</DialogClose>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1585,6 +1749,9 @@ export default function FormVideoDetail() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -95,11 +95,19 @@ export function CalendarPolriAddDetail() {
|
||||||
const details = response?.data?.data;
|
const details = response?.data?.data;
|
||||||
|
|
||||||
setDetail(details);
|
setDetail(details);
|
||||||
if (details) {
|
// if (details) {
|
||||||
|
// setDate({
|
||||||
|
// from: parseISO(details.startDate),
|
||||||
|
// to: parseISO(details.endDate),
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
if (details?.startDate && details?.endDate) {
|
||||||
setDate({
|
setDate({
|
||||||
from: parseISO(details.startDate),
|
from: parseISO(details.startDate),
|
||||||
to: parseISO(details.endDate),
|
to: parseISO(details.endDate),
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
// atau biarkan kosong sesuai kebutuhan
|
||||||
}
|
}
|
||||||
|
|
||||||
if (details?.assignedTo) {
|
if (details?.assignedTo) {
|
||||||
|
|
|
||||||
|
|
@ -1,78 +1,145 @@
|
||||||
|
// import { listDataAdvertisements } from "@/service/broadcast/broadcast";
|
||||||
|
// import { useEffect, useState } from "react";
|
||||||
|
// import * as React from "react";
|
||||||
|
|
||||||
|
// interface Advertisement {
|
||||||
|
// id: string;
|
||||||
|
// placements: string;
|
||||||
|
// imageUrl: string;
|
||||||
|
// [key: string]: any;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // // Simulasi fungsi API (replace dengan yang asli)
|
||||||
|
// // async function listDataAdvertisements(
|
||||||
|
// // page: number,
|
||||||
|
// // size: number,
|
||||||
|
// // search: string,
|
||||||
|
// // category: string,
|
||||||
|
// // status: string
|
||||||
|
// // ) {
|
||||||
|
// // // contoh struktur response dummy
|
||||||
|
// // return {
|
||||||
|
// // data: {
|
||||||
|
// // data: {
|
||||||
|
// // content: [
|
||||||
|
// // { id: "1", imageUrl: "/images/all-img/kiri1.png" },
|
||||||
|
// // { id: "2", imageUrl: "/images/all-img/kiri2.png" },
|
||||||
|
// // ],
|
||||||
|
// // totalElements: 2,
|
||||||
|
// // totalPages: 1,
|
||||||
|
// // },
|
||||||
|
// // },
|
||||||
|
// // };
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// const AdvertisementPlacements = (props: {
|
||||||
|
// placement: string;
|
||||||
|
// data: Advertisement[];
|
||||||
|
// loading: boolean;
|
||||||
|
// }) => {
|
||||||
|
// const [ads, setAds] = useState<Advertisement[] | undefined[]>([]);
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (!props.loading && props.data.length > 0) {
|
||||||
|
// console.log(
|
||||||
|
// "RRRRRR",
|
||||||
|
// props.data[0].placements.includes(props.placement),
|
||||||
|
// props.placement
|
||||||
|
// );
|
||||||
|
|
||||||
|
// const filtered = props.data.filter((a) =>
|
||||||
|
// a.placements.includes(props.placement)
|
||||||
|
// );
|
||||||
|
// let temps: Advertisement[] | undefined[] = [];
|
||||||
|
// temps[0] = filtered.find((b) => b.placements.includes("top"));
|
||||||
|
// temps[1] = filtered.find((b) => b.placements.includes("bottom"));
|
||||||
|
// setAds(temps);
|
||||||
|
// console.log("PPPPPP", filtered);
|
||||||
|
// }
|
||||||
|
// }, [props.data, props.loading]);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div
|
||||||
|
// className={`sticky top-0 space-y-4 ${
|
||||||
|
// props.placement == "left" ? "ml-14" : "mr-14"
|
||||||
|
// }`}
|
||||||
|
// >
|
||||||
|
// {props.loading && <p className="text-sm text-gray-500">Loading...</p>}
|
||||||
|
// {ads?.map(
|
||||||
|
// (ad) =>
|
||||||
|
// ad && (
|
||||||
|
// <img
|
||||||
|
// key={ad.id}
|
||||||
|
// src={ad.contentFileUrl}
|
||||||
|
// alt={`Banner ${ad.id}`}
|
||||||
|
// className="w-full"
|
||||||
|
// />
|
||||||
|
// )
|
||||||
|
// )}
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default AdvertisementPlacements;
|
||||||
import { listDataAdvertisements } from "@/service/broadcast/broadcast";
|
import { listDataAdvertisements } from "@/service/broadcast/broadcast";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
|
||||||
|
|
||||||
interface Advertisement {
|
interface Advertisement {
|
||||||
id: string;
|
id: string;
|
||||||
placements: string;
|
placements: string;
|
||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
|
contentFileUrl?: string;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Simulasi fungsi API (replace dengan yang asli)
|
|
||||||
// async function listDataAdvertisements(
|
|
||||||
// page: number,
|
|
||||||
// size: number,
|
|
||||||
// search: string,
|
|
||||||
// category: string,
|
|
||||||
// status: string
|
|
||||||
// ) {
|
|
||||||
// // contoh struktur response dummy
|
|
||||||
// return {
|
|
||||||
// data: {
|
|
||||||
// data: {
|
|
||||||
// content: [
|
|
||||||
// { id: "1", imageUrl: "/images/all-img/kiri1.png" },
|
|
||||||
// { id: "2", imageUrl: "/images/all-img/kiri2.png" },
|
|
||||||
// ],
|
|
||||||
// totalElements: 2,
|
|
||||||
// totalPages: 1,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
const AdvertisementPlacements = (props: {
|
const AdvertisementPlacements = (props: {
|
||||||
placement: string;
|
placement: string;
|
||||||
data: Advertisement[];
|
data: Advertisement[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const [ads, setAds] = useState<Advertisement[] | undefined[]>([]);
|
const [ads, setAds] = useState<Advertisement[] | undefined[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!props.loading && props.data.length > 0) {
|
if (!props.loading && props.data.length > 0) {
|
||||||
console.log(
|
|
||||||
"RRRRRR",
|
|
||||||
props.data[0].placements.includes(props.placement),
|
|
||||||
props.placement
|
|
||||||
);
|
|
||||||
|
|
||||||
const filtered = props.data.filter((a) =>
|
const filtered = props.data.filter((a) =>
|
||||||
a.placements.includes(props.placement)
|
a.placements.includes(props.placement)
|
||||||
);
|
);
|
||||||
|
|
||||||
let temps: Advertisement[] | undefined[] = [];
|
let temps: Advertisement[] | undefined[] = [];
|
||||||
temps[0] = filtered.find((b) => b.placements.includes("top"));
|
temps[0] = filtered.find((b) => b.placements.includes("top"));
|
||||||
temps[1] = filtered.find((b) => b.placements.includes("bottom"));
|
temps[1] = filtered.find((b) => b.placements.includes("bottom"));
|
||||||
setAds(temps);
|
setAds(temps);
|
||||||
console.log("PPPPPP", filtered);
|
|
||||||
}
|
}
|
||||||
}, [props.data, props.loading]);
|
}, [props.data, props.loading, props.placement]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`sticky top-0 space-y-4 ${
|
className={`sticky top-0 space-y-4 ${
|
||||||
props.placement == "left" ? "ml-14" : "mr-14"
|
props.placement === "left" ? "ml-14" : "mr-14"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{props.loading && <p className="text-sm text-gray-500">Loading...</p>}
|
{props.loading && <p className="text-sm text-gray-500">Loading...</p>}
|
||||||
|
|
||||||
{ads?.map(
|
{ads?.map(
|
||||||
(ad) =>
|
(ad) =>
|
||||||
ad && (
|
ad && (
|
||||||
|
<Dialog key={ad.id}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
<img
|
<img
|
||||||
key={ad.id}
|
src={ad.contentFileUrl || ad.imageUrl}
|
||||||
src={ad.contentFileUrl}
|
|
||||||
alt={`Banner ${ad.id}`}
|
alt={`Banner ${ad.id}`}
|
||||||
className="w-full"
|
className="w-full cursor-pointer rounded-lg shadow-md hover:opacity-90 transition"
|
||||||
/>
|
/>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="max-w-4xl p-0 bg-transparent border-0 shadow-none">
|
||||||
|
<img
|
||||||
|
src={ad.contentFileUrl || ad.imageUrl}
|
||||||
|
alt={`Banner Besar ${ad.id}`}
|
||||||
|
className="w-full h-auto rounded-lg"
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -533,16 +533,17 @@ const HeroNew = (props: { group?: string }) => {
|
||||||
|
|
||||||
<div className="relative w-full">
|
<div className="relative w-full">
|
||||||
{content && content.length > 0 && (
|
{content && content.length > 0 && (
|
||||||
|
<>
|
||||||
<Swiper
|
<Swiper
|
||||||
modules={[Autoplay, Navigation]}
|
modules={[Autoplay, Navigation]}
|
||||||
autoplay={{
|
autoplay={{
|
||||||
delay: 10000,
|
delay: 10000,
|
||||||
disableOnInteraction: false,
|
disableOnInteraction: false,
|
||||||
}}
|
}}
|
||||||
loop={true}
|
loop
|
||||||
navigation={{
|
navigation={{
|
||||||
nextEl: ".swiper-button-next",
|
nextEl: ".hero-next",
|
||||||
prevEl: ".swiper-button-prev",
|
prevEl: ".hero-prev",
|
||||||
}}
|
}}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
|
|
@ -580,29 +581,39 @@ const HeroNew = (props: { group?: string }) => {
|
||||||
<span className="text-red-600 text-[10px] lg:text-lg font-bold uppercase">
|
<span className="text-red-600 text-[10px] lg:text-lg font-bold uppercase">
|
||||||
{list?.categoryName}
|
{list?.categoryName}
|
||||||
</span>
|
</span>
|
||||||
<h2 className="text-[14px] lg:text-xl font-bold">{list?.title}</h2>
|
<h2 className="text-[14px] lg:text-xl font-bold">
|
||||||
|
{list?.title}
|
||||||
|
</h2>
|
||||||
<p className="text-[9px] lg:text-sm mt-2">
|
<p className="text-[9px] lg:text-sm mt-2">
|
||||||
{formatDateToIndonesian(new Date(list?.createdAt))}{" "}
|
{formatDateToIndonesian(new Date(list?.createdAt))}{" "}
|
||||||
{list?.timezone || "WIB"} | 👁 {list?.clickCount}
|
{list?.timezone || "WIB"} | 👁 {list?.clickCount}
|
||||||
</p>
|
</p>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<div className="absolute left-2 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full">
|
|
||||||
<Icon
|
|
||||||
icon="mdi:chevron-left"
|
|
||||||
className="w-5 lg:w-10 h-5 lg:h-10"
|
|
||||||
/>{" "}
|
|
||||||
</div>
|
|
||||||
<div className="absolute right-2 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full">
|
|
||||||
<Icon
|
|
||||||
icon="mdi:chevron-right"
|
|
||||||
className="w-5 lg:w-10 h-5 lg:h-10"
|
|
||||||
/>{" "}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
))}
|
))}
|
||||||
</Swiper>
|
</Swiper>
|
||||||
|
|
||||||
|
{/* Tombol navigasi — render SEKALI dan beri selector yang di-bind */}
|
||||||
|
<button
|
||||||
|
className="hero-prev absolute left-2 top-1/2 z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full"
|
||||||
|
aria-label="Previous"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon="mdi:chevron-left"
|
||||||
|
className="w-5 lg:w-10 h-5 lg:h-10"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="hero-next absolute right-2 top-1/2 z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full"
|
||||||
|
aria-label="Next"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon="mdi:chevron-right"
|
||||||
|
className="w-5 lg:w-10 h-5 lg:h-10"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -557,9 +557,9 @@
|
||||||
"question1": "WHAT CONTENT IS ON MEDIAHUB AND WHAT CATEGORIES ARE THERE IN IT?",
|
"question1": "WHAT CONTENT IS ON MEDIAHUB AND WHAT CATEGORIES ARE THERE IN IT?",
|
||||||
"answer1": "MediaHub has a variety of content such as news, videos, and documents categorized into topics such as education, entertainment, and current affairs.",
|
"answer1": "MediaHub has a variety of content such as news, videos, and documents categorized into topics such as education, entertainment, and current affairs.",
|
||||||
"question2": "HOW CAN MEDIAHUB CONTENT BE DOWNLOADED?",
|
"question2": "HOW CAN MEDIAHUB CONTENT BE DOWNLOADED?",
|
||||||
"answer2": "You can download content by clicking the download button available on each content on the MediaHub page.",
|
"answer2": "A=) Login first to be able to download B=) Select the photo size you want C=) Click the download button available on each content on the MediaHub page.",
|
||||||
"question3": "WHO CAN REGISTER AS A MEDIAHUB USER?",
|
"question3": "WHO CAN REGISTER AS A MEDIAHUB USER?",
|
||||||
"answer3": "Anyone who has an interest in the content on MediaHub can register as a user, either for personal or professional purposes.",
|
"answer3": "Anyone interested in MediaHub content can register as a user, including individuals and professionals within the General Public, Police, Journalists, and Presidential Staff Office (KSP) categories.",
|
||||||
"question4": "WHAT IS MEDIAHUB? AND WHAT ARE THE FEATURES IN IT?",
|
"question4": "WHAT IS MEDIAHUB? AND WHAT ARE THE FEATURES IN IT?",
|
||||||
"answer4": "MediaHub is a platform that provides various informative and educational content. Key features include search, download, and personalization of content.",
|
"answer4": "MediaHub is a platform that provides various informative and educational content. Key features include search, download, and personalization of content.",
|
||||||
"welcome": "Welcome To",
|
"welcome": "Welcome To",
|
||||||
|
|
|
||||||
|
|
@ -560,9 +560,9 @@
|
||||||
"question1": "APA SAJA KONTEN-KONTEN YANG ADA DI MEDIAHUB DAN KATEGORI DI DALAMNYA?",
|
"question1": "APA SAJA KONTEN-KONTEN YANG ADA DI MEDIAHUB DAN KATEGORI DI DALAMNYA?",
|
||||||
"answer1": "MediaHub memiliki beragam konten seperti berita, video, dan dokumen yang dikategorikan dalam topik seperti edukasi, hiburan, dan informasi terkini.",
|
"answer1": "MediaHub memiliki beragam konten seperti berita, video, dan dokumen yang dikategorikan dalam topik seperti edukasi, hiburan, dan informasi terkini.",
|
||||||
"question2": "BAGAIMANA KONTEN DARI MEDIAHUB DAPAT DIUNDUH?",
|
"question2": "BAGAIMANA KONTEN DARI MEDIAHUB DAPAT DIUNDUH?",
|
||||||
"answer2": "Anda dapat mengunduh konten dengan klik tombol unduh yang tersedia pada setiap konten di halaman MediaHub.",
|
"answer2": "A=) Login terlebih dahulu untuk dapat mengunduh. B=) Pilih size foto yang anda inginkan. C=) Klik tombol unduh yang tersedia pada setiap konten di halaman MediaHub.",
|
||||||
"question3": "SIAPA SAJA YANG DAPAT MENDAFTARKAN DIRI SEBAGAI PENGGUNA MEDIAHUB?",
|
"question3": "SIAPA SAJA YANG DAPAT MENDAFTARKAN DIRI SEBAGAI PENGGUNA MEDIAHUB?",
|
||||||
"answer3": "Semua orang yang memiliki minat terhadap konten di MediaHub dapat mendaftar sebagai pengguna, baik untuk personal maupun profesional.",
|
"answer3": "Semua orang yang memiliki minat terhadap konten di MediaHub dapat mendaftar sebagai pengguna, baik untuk personal maupun profesional yang tergabung dalam kategpri Masyarakat Umum. Anggota Polri, Jurnalis serta KSP",
|
||||||
"question4": "APA ITU MEDIAHUB? DAN APA SAJA FITUR YANG ADA DI DALAMNYA?",
|
"question4": "APA ITU MEDIAHUB? DAN APA SAJA FITUR YANG ADA DI DALAMNYA?",
|
||||||
"answer4": "MediaHub adalah platform yang menyediakan berbagai konten informatif dan edukatif. Fitur utama meliputi pencarian, pengunduhan, dan personalisasi konten.",
|
"answer4": "MediaHub adalah platform yang menyediakan berbagai konten informatif dan edukatif. Fitur utama meliputi pencarian, pengunduhan, dan personalisasi konten.",
|
||||||
"welcome": "Selamat Datang di",
|
"welcome": "Selamat Datang di",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue