fix: schedule live rport

This commit is contained in:
Sabda Yagra 2026-01-22 12:16:28 +07:00
commit bc1fe9f9eb
12 changed files with 1456 additions and 543 deletions

View File

@ -89,7 +89,8 @@ const columns: ColumnDef<any>[] = [
cell: ({ row, table }) => {
const original = row.original;
const isValid = original.isValid;
// const isValid = original.isValid;
const isRelevant = original.isRelevant;
const link = original.link;
const updateRow = (data: Partial<any>) => {
@ -99,10 +100,10 @@ const columns: ColumnDef<any>[] = [
const handleValid = async () => {
try {
await validateMediaLink(original.id, true);
updateRow({
isValid: true,
isRelevant: true,
});
table.options.meta?.refetchData?.();
} catch (err: any) {
toast.error(err.message);
}
@ -113,8 +114,9 @@ const columns: ColumnDef<any>[] = [
await validateMediaLink(original.id, false);
updateRow({
isValid: false,
isRelevant: false,
});
table.options.meta?.refetchData?.();
} catch (err: any) {
toast.error(err.message);
}
@ -124,24 +126,55 @@ const columns: ColumnDef<any>[] = [
return <span className="text-muted-foreground">-</span>;
}
if (isValid === true) {
if (isRelevant === true) {
return (
<Button
size="sm"
className="bg-green-600 hover:bg-green-700"
disabled
>
Valid
Relevan
</Button>
);
}
return (
<div className="flex gap-2">
<Button size="sm" variant="outline" onClick={handleValid}>
<Button
size="sm"
variant="outline"
onClick={handleValid}
className="flex items-center"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M18.7 7.2c-.4-.4-1-.4-1.4 0l-7.5 7.5l-3.1-3.1c-.4-.4-1-.4-1.4 0s-.4 1 0 1.4l3.8 3.8c.2.2.4.3.7.3s.5-.1.7-.3l8.2-8.2c.4-.4.4-1 0-1.4"
/>
</svg>
Relevan
</Button>
<Button size="sm" variant="outline" onClick={handleInvalid}>
<Button size="sm" variant="outline" onClick={handleInvalid} className="flex text-center items-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 24 24"
>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
d="M6.758 17.243L12.001 12m5.243-5.243L12 12m0 0L6.758 6.757M12.001 12l5.243 5.243"
/>
</svg>
Tidak Relevan
</Button>
</div>

View File

@ -124,6 +124,9 @@ const NewsDetailTable = () => {
)
);
},
refetchData: () => {
fetchData();
},
},
state: {
sorting,
@ -163,7 +166,7 @@ const NewsDetailTable = () => {
pageIndex: 0,
pageSize: Number(showData),
});
}, [page, showData]);
}, [page, showData, id]);
async function fetchData() {
try {

View File

@ -52,32 +52,34 @@ const columns: ColumnDef<any>[] = [
header: "Judul",
cell: ({ row }) => <span>{row.getValue("title")}</span>,
},
// {
// accessorKey: "resultTotal",
// header: () => <div className="text-center w-full">Jumlah Amplifikasi</div>,
// cell: ({ row }) => {
// const value = row.getValue("resultTotal") as number | string | null;
{
accessorKey: "resultTotal",
header: () => <div className="text-center w-full">Total Artikel</div>,
cell: ({ row }) => {
const value = row.getValue("resultTotal") as number | string | null;
// const finalValue =
// value === null || value === undefined || value === ""
// ? 0
// : Number(value);
const finalValue =
value === null || value === undefined || value === ""
? 0
: Number(value);
// return <div className="text-center w-full">{finalValue}</div>;
// },
// },
return <div className="text-center w-full">{finalValue}</div>;
},
},
{
accessorKey: "amplification",
header: () => <div className="text-center w-full">Jumlah Amplifikasi</div>,
cell: ({ row }) => {
const totalRaw = row.getValue("amplification") as number | string | null;
const raw = row.getValue("amplification") as string | null;
const total =
totalRaw === null || totalRaw === undefined || totalRaw === ""
? 0
: Number(totalRaw);
let total = 0;
let invalidTotal = 0;
const invalidTotal = 0;
if (raw && typeof raw === "string") {
const parts = raw.split("/").map((v) => v.trim());
total = Number(parts[0]) || 0;
invalidTotal = Number(parts[1]) || 0;
}
return (
<div className="text-center w-full font-medium">

View File

@ -891,7 +891,6 @@ const EventModal = ({
const resCsrf = await getCsrfToken();
const csrfToken = resCsrf?.data?.token;
// console.log("CSRF TOKEN : ", csrfToken);
const headers = {
"X-XSRF-TOKEN": csrfToken,
};

View File

@ -22,7 +22,7 @@ import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2";
import { useTranslations } from "next-intl";
const useTableColumns = (activeTab: "ta" | "daily" | "special") => {
const useTableColumns = (activeTab: "ta" | "daily" | "special" |"mabes-koor") => {
const t = useTranslations("Table");
const columns: ColumnDef<any>[] = [
{

View File

@ -75,6 +75,7 @@ interface Detail {
youtubeUrl: string;
needApprovalFrom: number;
uploadedById: number;
statusId?: number;
}
export default function FormDetailLiveReport() {
@ -176,21 +177,68 @@ export default function FormDetailLiveReport() {
statusId: Number(status),
message: description,
isPublish: status === "2",
placements: schedulePlacements?.filter((val) => val != "all")?.join(","),
placements: schedulePlacements?.filter((val) => val !== "all")?.join(","),
};
loading();
const response = await postApprovalSchedule(data);
close();
setModalOpen(false);
if (response?.error) {
error(response?.message);
return false;
error(response?.message || "Gagal menyimpan data");
return;
}
initState();
return false;
// ✅ update UI lokal (optimistic)
setDetail((prev) =>
prev
? {
...prev,
statusId: Number(status),
}
: prev,
);
Swal.fire({
icon: "success",
title: "Berhasil",
text:
status === "2"
? "Jadwal berhasil disetujui"
: status === "3"
? "Jadwal dikembalikan untuk revisi"
: "Jadwal berhasil ditolak",
confirmButtonText: "OK",
}).then((result) => {
if (result.isConfirmed) {
router.push("/contributor/schedule/live-report");
}
});
}
// async function save() {
// const data = {
// scheduleId: Number(id),
// statusId: Number(status),
// message: description,
// isPublish: status === "2",
// placements: schedulePlacements?.filter((val) => val != "all")?.join(","),
// };
// loading();
// const response = await postApprovalSchedule(data);
// close();
// setModalOpen(false);
// if (response?.error) {
// error(response?.message);
// return false;
// }
// initState();
// return false;
// }
const [schedulePlacements, setSchedulePlacements] = useState<string[]>([]);
const setupPlacement = (placement: string, checked: boolean) => {
@ -224,6 +272,15 @@ export default function FormDetailLiveReport() {
setSchedulePlacements(temp);
};
const isCreator = Number(detail?.uploadedById) === Number(userId);
const isApprover =
Number(detail?.needApprovalFrom) === Number(userLevelId) &&
Number(userLevelNumber) < 2;
const isAlreadyProcessed =
detail?.statusId === 2 || detail?.statusId === 3 || detail?.statusId === 4;
return (
<div className="flex flex-col lg:flex-row gap-2">
<Card className="w-full lg:w-9/12">
@ -284,7 +341,7 @@ export default function FormDetailLiveReport() {
variant={"outline"}
className={cn(
"w-[280px] lg:w-[250px] justify-start text-left font-normal px-0 md:px-0 lg:px-4",
!date && "text-muted-foreground"
!date && "text-muted-foreground",
)}
>
<CalendarIcon size={15} className="mr-3" />
@ -494,7 +551,38 @@ export default function FormDetailLiveReport() {
</AccordionItem>
</Accordion>
{Number(detail?.needApprovalFrom) == Number(userLevelId) &&
{(isApprover || isCreator) && !isAlreadyProcessed && (
<div className="flex flex-col gap-2 p-3">
<Button
onClick={() => actionApproval("2")}
color="primary"
type="button"
>
<Icon icon="fa:check" className="mr-3" />
{t("accept", { defaultValue: "Accept" })}
</Button>
<Button
onClick={() => actionApproval("3")}
className="bg-orange-400 hover:bg-orange-300"
type="button"
>
<Icon icon="fa:comment-o" className="mr-3" />
{t("revision", { defaultValue: "Revision" })}
</Button>
<Button
onClick={() => actionApproval("4")}
color="destructive"
type="button"
>
<Icon icon="fa:times" className="mr-3" />
{t("reject", { defaultValue: "Reject" })}
</Button>
</div>
)}
{/* {Number(detail?.needApprovalFrom) == Number(userLevelId) &&
Number(userLevelNumber) < 2 ? (
Number(detail?.uploadedById) == Number(userId) ? (
""
@ -527,13 +615,15 @@ export default function FormDetailLiveReport() {
)
) : (
""
)}
)} */}
</Card>
<Dialog open={modalOpen} onOpenChange={setModalOpen}>
<DialogContent className="overflow-y-auto">
<DialogHeader>
<DialogTitle>{t("leave-comment", { defaultValue: "Leave Comment" })}</DialogTitle>
<DialogTitle>
{t("leave-comment", { defaultValue: "Leave Comment" })}
</DialogTitle>
</DialogHeader>
<div className="flex flex-col gap-1 text-sm">
<p>
@ -544,15 +634,15 @@ export default function FormDetailLiveReport() {
status === "2"
? "text-primary"
: status === "3"
? "text-warning"
: "text-destructive"
? "text-warning"
: "text-destructive"
}
>
{status === "2"
? "Disetujui"
: status === "3"
? "Revisi"
: "Ditolak"}
? "Revisi"
: "Ditolak"}
</span>
</p>
{status === "2" && (

View File

@ -43,7 +43,7 @@ import { getCsrfToken } from "@/service/auth";
import { loading } from "@/lib/swal";
import { useTranslations } from "next-intl";
import dynamic from "next/dynamic";
import { cn } from "@/lib/utils";
import { cn, getCookiesDecrypt } from "@/lib/utils";
import {
Popover,
PopoverContent,
@ -181,6 +181,33 @@ export default function FormTaskTa() {
mode: "all",
});
const [profile, setProfile] = useState<any>(null);
const userLevelId = Number(getCookiesDecrypt("ulie"));
const roleId = Number(getCookiesDecrypt("urie"));
const userId = Number(getCookiesDecrypt("uie"));
const MABES_LEVEL_ID = 216; // userLevelId Mabes Polri
const APPROVER_ROLE_ID = 3; // roleId Approver
const isMabes = userLevelId === MABES_LEVEL_ID;
const isApprover = roleId === APPROVER_ROLE_ID;
const isMabesApprover =
userLevelId === MABES_LEVEL_ID && roleId === APPROVER_ROLE_ID;
const shouldHideExpert = isMabes && isApprover;
useEffect(() => {
async function fetchUserLevel() {
try {
const res = await getUserLevelForAssignments();
setProfile(res?.data?.data);
} catch (e) {
console.error("Failed fetch user level", e);
}
}
fetchUserLevel();
}, []);
useEffect(() => {
getDataAdditional();
}, []);
@ -352,55 +379,124 @@ export default function FormTaskTa() {
// // });
// };
// const save = async (data: TaskSchema) => {
// const cleanedLinks = links
// .map((link) => link.trim())
// .filter((link) => link.startsWith("http"));
// const requestData = {
// ...data,
// // assignedToUsers: handleExpertChange(),
// assignedToUsers: isMabesApprover ? "464" : handleExpertChange(),
// assignmentType: taskType,
// assignmentTypeId: type,
// expertCompetencies: Array.from(selectedCompetencies).join(","),
// attachmentUrl: cleanedLinks,
// };
// console.log("FINAL ASSIGNED TO:", {
// isMabesApprover,
// assignedToUsers: isMabesApprover
// ? String(roleId)
// : handleExpertChange(),
// });
// const response = await createTaskTa(requestData);
// const id = String(response?.data?.data.id);
// // Set block table TA
// localStorage.setItem("TA_UPLOAD_IN_PROGRESS", "true");
// loading(); // SHOW SWAL LOADING
// // Kumpulkan semua upload
// const allUploads: Promise<any>[] = [];
// imageFiles.forEach((item, idx) =>
// allUploads.push(uploadResumableFile(idx, id, item, "1", "0"))
// );
// videoFiles.forEach((item, idx) =>
// allUploads.push(uploadResumableFile(idx, id, item, "2", "0"))
// );
// textFiles.forEach((item, idx) =>
// allUploads.push(uploadResumableFile(idx, id, item, "3", "0"))
// );
// audioFiles.forEach((item, idx) =>
// allUploads.push(uploadResumableFile(idx, id, item, "4", "0"))
// );
// // Tunggu upload selesai
// await Promise.all(allUploads);
// // Hapus flag
// localStorage.removeItem("TA_UPLOAD_IN_PROGRESS");
// // Close loading + redirect
// successSubmit("/in/contributor/task-ta");
// };
const save = async (data: TaskSchema) => {
const cleanedLinks = links
.map((link) => link.trim())
.filter((link) => link.startsWith("http"));
try {
loading();
const requestData = {
...data,
assignedToUsers: handleExpertChange(),
assignmentType: taskType,
assignmentTypeId: type,
expertCompetencies: Array.from(selectedCompetencies).join(","),
attachmentUrl: cleanedLinks,
};
const cleanedLinks = links
.map((link) => link.trim())
.filter((link) => link.startsWith("http"));
const response = await createTaskTa(requestData);
const id = String(response?.data?.data.id);
const requestData = {
...data,
// assignedToUsers: isMabesApprover ? "464" : handleExpertChange(),
assignedToUsers: isMabesApprover ? "464" : handleExpertChange(),
assignmentType: taskType,
assignmentTypeId: type,
expertCompetencies: Array.from(selectedCompetencies).join(","),
attachmentUrl: cleanedLinks,
};
// Set block table TA
localStorage.setItem("TA_UPLOAD_IN_PROGRESS", "true");
const response = await createTaskTa(requestData);
loading(); // SHOW SWAL LOADING
if (!response?.data?.data?.id) {
throw new Error("Gagal membuat task");
}
// Kumpulkan semua upload
const allUploads: Promise<any>[] = [];
const assignmentId = String(response.data.data.id);
imageFiles.forEach((item, idx) =>
allUploads.push(uploadResumableFile(idx, id, item, "1", "0"))
);
const uploads: Promise<any>[] = [];
videoFiles.forEach((item, idx) =>
allUploads.push(uploadResumableFile(idx, id, item, "2", "0"))
);
imageFiles.forEach((file, i) =>
uploads.push(uploadResumableFile(i, assignmentId, file, "1", "0"))
);
textFiles.forEach((item, idx) =>
allUploads.push(uploadResumableFile(idx, id, item, "3", "0"))
);
videoFiles.forEach((file, i) =>
uploads.push(uploadResumableFile(i, assignmentId, file, "2", "0"))
);
audioFiles.forEach((item, idx) =>
allUploads.push(uploadResumableFile(idx, id, item, "4", "0"))
);
textFiles.forEach((file, i) =>
uploads.push(uploadResumableFile(i, assignmentId, file, "3", "0"))
);
// Tunggu upload selesai
await Promise.all(allUploads);
audioFiles.forEach((file, i) =>
uploads.push(uploadResumableFile(i, assignmentId, file, "4", "0"))
);
// Hapus flag
localStorage.removeItem("TA_UPLOAD_IN_PROGRESS");
await Promise.all(uploads);
// Close loading + redirect
successSubmit("/in/contributor/task-ta");
successSubmit("/in/contributor/task-ta");
} catch (err: any) {
console.error("SUBMIT ERROR:", err);
Swal.fire({
icon: "error",
title: "Gagal",
text:
err?.response?.data?.message ||
err?.message ||
"Terjadi kesalahan, data tidak tersimpan",
});
}
};
const onSubmit = (data: TaskSchema) => {
@ -543,46 +639,91 @@ export default function FormTaskTa() {
// upload.start();
// }
// function uploadResumableFile(
// idx: number,
// id: string,
// file: any,
// fileTypeId: string,
// duration: string
// ) {
// return new Promise(async (resolve, reject) => {
// const resCsrf = await getCsrfToken();
// const csrfToken = resCsrf?.data?.token;
// const upload = new Upload(file, {
// endpoint: `${process.env.NEXT_PUBLIC_API}/assignment-expert/file/upload`,
// headers: { "X-XSRF-TOKEN": csrfToken },
// retryDelays: [0, 3000, 6000, 12000],
// chunkSize: 20000,
// metadata: {
// assignmentId: id,
// filename: file.name,
// contentType: file.type,
// fileTypeId,
// duration,
// },
// onBeforeRequest(req) {
// req.getUnderlyingObject().withCredentials = true;
// },
// onError(err) {
// console.error("Upload error:", err);
// reject(err);
// },
// onSuccess() {
// console.log("Upload selesai:", file.name);
// resolve(true);
// },
// });
// upload.start();
// });
// }
function uploadResumableFile(
idx: number,
id: string,
file: any,
file: File,
fileTypeId: string,
duration: string
) {
return new Promise(async (resolve, reject) => {
const resCsrf = await getCsrfToken();
const csrfToken = resCsrf?.data?.token;
try {
const resCsrf = await getCsrfToken();
const csrfToken = resCsrf?.data?.token;
const upload = new Upload(file, {
endpoint: `${process.env.NEXT_PUBLIC_API}/assignment-expert/file/upload`,
headers: { "X-XSRF-TOKEN": csrfToken },
retryDelays: [0, 3000, 6000, 12000],
chunkSize: 20000,
metadata: {
assignmentId: id,
filename: file.name,
contentType: file.type,
fileTypeId,
duration,
},
const upload = new Upload(file, {
endpoint: `${process.env.NEXT_PUBLIC_API}/assignment-expert/file/upload`,
headers: { "X-XSRF-TOKEN": csrfToken },
retryDelays: [0, 3000, 6000],
chunkSize: 20000,
metadata: {
assignmentId: id,
filename: file.name,
contentType: file.type,
fileTypeId,
duration,
},
onBeforeRequest(req) {
req.getUnderlyingObject().withCredentials = true;
},
onBeforeRequest(req) {
req.getUnderlyingObject().withCredentials = true;
},
onError(err) {
console.error("Upload error:", err);
reject(err);
},
onError(error) {
reject(error);
},
onSuccess() {
console.log("Upload selesai:", file.name);
resolve(true);
},
});
onSuccess() {
resolve(true);
},
});
upload.start();
upload.start();
} catch (err) {
reject(err);
}
});
}
@ -718,101 +859,109 @@ export default function FormTaskTa() {
</PopoverContent>
</Popover>
</div>
<div className="mt-5 space-y-2">
<Label>
{t("areas-expertise", { defaultValue: "Areas Expertise" })}
</Label>
<div className="flex flex-wrap gap-4">
{userCompetencies?.map((item: any) => (
<div className="flex items-center gap-2" key={item.id}>
<Checkbox
id={`comp-${item.id}`}
checked={selectedCompetencies.has(item.id)}
onCheckedChange={() => handleCompetencyChange(item.id)}
/>
<Label htmlFor={`comp-${item.id}`}>{item.name}</Label>
</div>
))}
</div>
</div>
<div className="mt-5 space-y-2">
<Label>
{t("choose-expert", { defaultValue: "Choose Expert" })}
</Label>
<div className="flex flex-wrap gap-4">
<Dialog>
<DialogTrigger asChild>
<Button variant="soft" size="sm" color="primary">
[{"Pilih Tenaga Ahli"}]
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
<DialogHeader>
<DialogTitle>Daftar Tenaga Ahli</DialogTitle>
</DialogHeader>
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
{listExpert?.map((expert: any) => (
<div key={expert.id} className="border p-2">
<Label className="flex items-center">
<Checkbox
checked={checkedLevels.has(expert.id)}
onCheckedChange={() =>
handleCheckboxChange(expert.id)
}
className="mr-3"
/>
<div className="flex flex-col gap-2">
<div className="font-bold">{expert.fullname}</div>
<div className="italic">({expert.username})</div>
</div>
</Label>
</div>
))}
{!isMabesApprover && (
<div className="mt-5 space-y-2">
<Label>
{t("areas-expertise", { defaultValue: "Areas Expertise" })}
</Label>
<div className="flex flex-wrap gap-4">
{userCompetencies?.map((item: any) => (
<div className="flex items-center gap-2" key={item.id}>
<Checkbox
id={`comp-${item.id}`}
checked={selectedCompetencies.has(item.id)}
onCheckedChange={() => handleCompetencyChange(item.id)}
/>
<Label htmlFor={`comp-${item.id}`}>{item.name}</Label>
</div>
</DialogContent>
</Dialog>
</div>
{checkedLevels.size > 0 && (
<div className="mt-3">
<Label className="text-sm text-gray-600 mb-2 block">
Tenaga Ahli Terpilih ({checkedLevels.size})
</Label>
<div className="flex flex-wrap gap-2">
{Array.from(checkedLevels).map((expertId) => {
const expert = listExpert?.find(
(exp: any) => exp.id === expertId
);
return expert ? (
<div
key={expert.id}
className="inline-flex items-center gap-2 bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1.5 rounded-full border border-blue-200"
>
<span>{expert.fullname}</span>
<button
type="button"
onClick={() => handleCheckboxChange(expert.id)}
className="ml-1 text-blue-600 hover:text-blue-800 hover:bg-blue-200 rounded-full p-0.5 transition-colors"
title="Remove expert"
>
<svg
className="w-3 h-3"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button>
</div>
) : null;
})}
</div>
))}
</div>
)}
</div>
</div>
)}
{!isMabesApprover && (
<div className="mt-5 space-y-2">
<Label>
{t("choose-expert", { defaultValue: "Choose Expert" })}
</Label>
<div className="flex flex-wrap gap-4">
<Dialog>
<DialogTrigger asChild>
<Button variant="soft" size="sm" color="primary">
[{"Pilih Tenaga Ahli"}]
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
<DialogHeader>
<DialogTitle>Daftar Tenaga Ahli</DialogTitle>
</DialogHeader>
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
{listExpert?.map((expert: any) => (
<div key={expert.id} className="border p-2">
<Label className="flex items-center">
<Checkbox
checked={checkedLevels.has(expert.id)}
onCheckedChange={() =>
handleCheckboxChange(expert.id)
}
className="mr-3"
/>
<div className="flex flex-col gap-2">
<div className="font-bold">
{expert.fullname}
</div>
<div className="italic">
({expert.username})
</div>
</div>
</Label>
</div>
))}
</div>
</DialogContent>
</Dialog>
</div>
{checkedLevels.size > 0 && (
<div className="mt-3">
<Label className="text-sm text-gray-600 mb-2 block">
Tenaga Ahli Terpilih ({checkedLevels.size})
</Label>
<div className="flex flex-wrap gap-2">
{Array.from(checkedLevels).map((expertId) => {
const expert = listExpert?.find(
(exp: any) => exp.id === expertId
);
return expert ? (
<div
key={expert.id}
className="inline-flex items-center gap-2 bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1.5 rounded-full border border-blue-200"
>
<span>{expert.fullname}</span>
<button
type="button"
onClick={() => handleCheckboxChange(expert.id)}
className="ml-1 text-blue-600 hover:text-blue-800 hover:bg-blue-200 rounded-full p-0.5 transition-colors"
title="Remove expert"
>
<svg
className="w-3 h-3"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button>
</div>
) : null;
})}
</div>
</div>
)}
</div>
)}
<div className="mt-5 space-y-2">
<Label>{t("description", { defaultValue: "Description" })}</Label>
<Controller
@ -946,7 +1095,9 @@ export default function FormTaskTa() {
<Input
type="url"
className="border rounded p-2 w-full"
placeholder={`Masukkan link berita ${index + 1}`}
placeholder={`Masukkan link berita ${
index + 1
} | Contoh: https://www.detik.com`}
value={link}
onChange={(e) =>
handleLinkChange(index, e.target.value)

View File

@ -168,6 +168,13 @@ export function getMenuList(pathname: string, t: any): Group[] {
icon: "heroicons:shopping-cart",
children: [],
},
{
href: "/contributor/task-ta",
label: "penugasan TA",
active: pathname.includes("/contributor/task-ta"),
icon: "heroicons:shopping-cart",
children: [],
},
],
},
],

View File

@ -10,7 +10,7 @@ importers:
dependencies:
'@ckeditor/ckeditor5-react':
specifier: ^6.2.0
version: 6.3.0(@ckeditor/ckeditor5-core@46.0.0)(@ckeditor/ckeditor5-editor-multi-root@46.0.0)(@ckeditor/ckeditor5-engine@46.0.0)(@ckeditor/ckeditor5-utils@46.0.0)(@ckeditor/ckeditor5-watchdog@46.0.0)(react@18.3.1)
version: 6.3.0(@ckeditor/ckeditor5-core@47.1.0)(@ckeditor/ckeditor5-editor-multi-root@47.1.0)(@ckeditor/ckeditor5-engine@47.1.0)(@ckeditor/ckeditor5-utils@47.1.0)(@ckeditor/ckeditor5-watchdog@47.1.0)(react@18.3.1)
'@dnd-kit/core':
specifier: ^6.1.0
version: 6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -223,7 +223,10 @@ importers:
version: 8.5.1(embla-carousel@8.5.1)
embla-carousel-react:
specifier: ^8.1.3
version: 8.5.1(react@18.3.1)
version: 8.6.0(react@18.3.1)
file-saver:
specifier: ^2.0.5
version: 2.0.5
framer-motion:
specifier: ^11.15.0
version: 11.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -394,7 +397,10 @@ importers:
version: 0.9.9(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
wavesurfer.js:
specifier: ^7.8.16
version: 7.8.16
version: 7.11.0
xlsx:
specifier: ^0.18.5
version: 0.18.5
yup:
specifier: ^1.6.1
version: 1.6.1
@ -3061,8 +3067,12 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
agent-base@7.1.3:
resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==}
adler-32@1.3.1:
resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
engines: {node: '>=0.8'}
agent-base@7.1.4:
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
engines: {node: '>= 14'}
ajv@6.12.6:
@ -3336,6 +3346,10 @@ packages:
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
cfb@1.2.2:
resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==}
engines: {node: '>=0.8'}
chalk@2.3.0:
resolution: {integrity: sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==}
engines: {node: '>=4'}
@ -3447,8 +3461,12 @@ packages:
code-block-writer@12.0.0:
resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==}
collect-v8-coverage@1.0.2:
resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==}
codepage@1.15.0:
resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==}
engines: {node: '>=0.8'}
collect-v8-coverage@1.0.3:
resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==}
color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
@ -3548,6 +3566,11 @@ packages:
typescript:
optional: true
crc-32@1.2.2:
resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
engines: {node: '>=0.8'}
hasBin: true
cross-env@7.0.3:
resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==}
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
@ -4223,6 +4246,9 @@ packages:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
file-saver@2.0.5:
resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==}
file-selector@2.1.2:
resolution: {integrity: sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==}
engines: {node: '>= 12'}
@ -4283,8 +4309,16 @@ packages:
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
engines: {node: '>=12.20.0'}
framer-motion@11.15.0:
resolution: {integrity: sha512-MLk8IvZntxOMg7lDBLw2qgTHHv664bYoYmnFTmE0Gm/FW67aOJk0WM3ctMcG+Xhcv+vh5uyyXwxvxhSeJzSe+w==}
forwarded@0.2.0:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'}
frac@1.1.2:
resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==}
engines: {node: '>=0.8'}
framer-motion@11.18.2:
resolution: {integrity: sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==}
peerDependencies:
'@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0
@ -6707,8 +6741,12 @@ packages:
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
stable-hash@0.0.4:
resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==}
ssf@0.11.2:
resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==}
engines: {node: '>=0.8'}
stable-hash@0.0.5:
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
stack-utils@2.0.6:
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
@ -7330,10 +7368,22 @@ packages:
engines: {node: '>= 8'}
hasBin: true
wmf@1.0.2:
resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==}
engines: {node: '>=0.8'}
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
word@0.3.0:
resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==}
engines: {node: '>=0.8'}
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@ -7373,6 +7423,11 @@ packages:
utf-8-validate:
optional: true
xlsx@0.18.5:
resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
engines: {node: '>=0.8'}
hasBin: true
xml-name-validator@5.0.0:
resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
engines: {node: '>=18'}
@ -7855,9 +7910,9 @@ snapshots:
'@ckeditor/ckeditor5-adapter-ckfinder@46.0.0':
dependencies:
'@ckeditor/ckeditor5-core': 46.0.0
'@ckeditor/ckeditor5-upload': 46.0.0
ckeditor5: 46.0.0
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-upload': 47.1.0
ckeditor5: 47.1.0
'@ckeditor/ckeditor5-alignment@41.3.1':
dependencies:
@ -7918,15 +7973,13 @@ snapshots:
'@ckeditor/ckeditor5-block-quote@46.0.0':
dependencies:
'@ckeditor/ckeditor5-core': 46.0.0
'@ckeditor/ckeditor5-enter': 46.0.0
'@ckeditor/ckeditor5-icons': 46.0.0
'@ckeditor/ckeditor5-typing': 46.0.0
'@ckeditor/ckeditor5-ui': 46.0.0
'@ckeditor/ckeditor5-utils': 46.0.0
ckeditor5: 46.0.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-enter': 47.1.0
'@ckeditor/ckeditor5-icons': 47.1.0
'@ckeditor/ckeditor5-typing': 47.1.0
'@ckeditor/ckeditor5-ui': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
ckeditor5: 47.1.0
'@ckeditor/ckeditor5-bookmark@46.0.0':
dependencies:
@ -7991,11 +8044,9 @@ snapshots:
'@ckeditor/ckeditor5-cloud-services@46.0.0':
dependencies:
'@ckeditor/ckeditor5-core': 46.0.0
'@ckeditor/ckeditor5-utils': 46.0.0
ckeditor5: 46.0.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
ckeditor5: 47.1.0
'@ckeditor/ckeditor5-code-block@41.3.1':
dependencies:
@ -8062,8 +8113,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 46.0.0
ckeditor5: 46.0.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-decoupled@46.0.0':
dependencies:
@ -8091,18 +8140,36 @@ snapshots:
'@ckeditor/ckeditor5-utils': 46.0.0
ckeditor5: 46.0.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-emoji@46.0.0':
dependencies:
'@ckeditor/ckeditor5-core': 46.0.0
'@ckeditor/ckeditor5-icons': 46.0.0
'@ckeditor/ckeditor5-mention': 46.0.0
'@ckeditor/ckeditor5-typing': 46.0.0
'@ckeditor/ckeditor5-ui': 46.0.0
'@ckeditor/ckeditor5-utils': 46.0.0
ckeditor5: 46.0.0
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-engine': 47.1.0
'@ckeditor/ckeditor5-ui': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
ckeditor5: 47.1.0
es-toolkit: 1.39.5
'@ckeditor/ckeditor5-editor-multi-root@47.1.0':
dependencies:
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-engine': 47.1.0
'@ckeditor/ckeditor5-ui': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
ckeditor5: 47.1.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-emoji@47.1.0':
dependencies:
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-icons': 47.1.0
'@ckeditor/ckeditor5-mention': 47.1.0
'@ckeditor/ckeditor5-typing': 47.1.0
'@ckeditor/ckeditor5-ui': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
ckeditor5: 47.1.0
es-toolkit: 1.39.5
fuzzysort: 3.1.0
transitivePeerDependencies:
@ -8369,18 +8436,16 @@ snapshots:
'@ckeditor/ckeditor5-media-embed@46.0.0':
dependencies:
'@ckeditor/ckeditor5-clipboard': 46.0.0
'@ckeditor/ckeditor5-core': 46.0.0
'@ckeditor/ckeditor5-engine': 46.0.0
'@ckeditor/ckeditor5-icons': 46.0.0
'@ckeditor/ckeditor5-typing': 46.0.0
'@ckeditor/ckeditor5-ui': 46.0.0
'@ckeditor/ckeditor5-undo': 46.0.0
'@ckeditor/ckeditor5-utils': 46.0.0
'@ckeditor/ckeditor5-widget': 46.0.0
ckeditor5: 46.0.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-clipboard': 47.1.0
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-engine': 47.1.0
'@ckeditor/ckeditor5-icons': 47.1.0
'@ckeditor/ckeditor5-typing': 47.1.0
'@ckeditor/ckeditor5-ui': 47.1.0
'@ckeditor/ckeditor5-undo': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
'@ckeditor/ckeditor5-widget': 47.1.0
ckeditor5: 47.1.0
'@ckeditor/ckeditor5-mention@46.0.0':
dependencies:
@ -8439,25 +8504,23 @@ snapshots:
'@ckeditor/ckeditor5-engine': 46.0.0
ckeditor5: 46.0.0
'@ckeditor/ckeditor5-react@6.3.0(@ckeditor/ckeditor5-core@46.0.0)(@ckeditor/ckeditor5-editor-multi-root@46.0.0)(@ckeditor/ckeditor5-engine@46.0.0)(@ckeditor/ckeditor5-utils@46.0.0)(@ckeditor/ckeditor5-watchdog@46.0.0)(react@18.3.1)':
'@ckeditor/ckeditor5-react@6.3.0(@ckeditor/ckeditor5-core@47.1.0)(@ckeditor/ckeditor5-editor-multi-root@47.1.0)(@ckeditor/ckeditor5-engine@47.1.0)(@ckeditor/ckeditor5-utils@47.1.0)(@ckeditor/ckeditor5-watchdog@47.1.0)(react@18.3.1)':
dependencies:
'@ckeditor/ckeditor5-core': 46.0.0
'@ckeditor/ckeditor5-editor-multi-root': 46.0.0
'@ckeditor/ckeditor5-engine': 46.0.0
'@ckeditor/ckeditor5-utils': 46.0.0
'@ckeditor/ckeditor5-watchdog': 46.0.0
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-editor-multi-root': 47.1.0
'@ckeditor/ckeditor5-engine': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
'@ckeditor/ckeditor5-watchdog': 47.1.0
prop-types: 15.8.1
react: 18.3.1
'@ckeditor/ckeditor5-remove-format@46.0.0':
dependencies:
'@ckeditor/ckeditor5-core': 46.0.0
'@ckeditor/ckeditor5-icons': 46.0.0
'@ckeditor/ckeditor5-ui': 46.0.0
'@ckeditor/ckeditor5-utils': 46.0.0
ckeditor5: 46.0.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-icons': 47.1.0
'@ckeditor/ckeditor5-ui': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
ckeditor5: 47.1.0
'@ckeditor/ckeditor5-restricted-editing@46.0.0':
dependencies:
@ -8499,12 +8562,12 @@ snapshots:
'@ckeditor/ckeditor5-source-editing@46.0.0':
dependencies:
'@ckeditor/ckeditor5-core': 46.0.0
'@ckeditor/ckeditor5-icons': 46.0.0
'@ckeditor/ckeditor5-theme-lark': 46.0.0
'@ckeditor/ckeditor5-ui': 46.0.0
'@ckeditor/ckeditor5-utils': 46.0.0
ckeditor5: 46.0.0
'@ckeditor/ckeditor5-core': 47.1.0
'@ckeditor/ckeditor5-icons': 47.1.0
'@ckeditor/ckeditor5-theme-lark': 47.1.0
'@ckeditor/ckeditor5-ui': 47.1.0
'@ckeditor/ckeditor5-utils': 47.1.0
ckeditor5: 47.1.0
'@ckeditor/ckeditor5-special-characters@46.0.0':
dependencies:
@ -8671,8 +8734,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 46.0.0
ckeditor5: 46.0.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@csstools/color-helpers@5.0.2': {}
@ -10730,7 +10791,9 @@ snapshots:
acorn@8.14.0: {}
agent-base@7.1.3: {}
adler-32@1.3.1: {}
agent-base@7.1.4: {}
ajv@6.12.6:
dependencies:
@ -11054,6 +11117,11 @@ snapshots:
ccount@2.0.1: {}
cfb@1.2.2:
dependencies:
adler-32: 1.3.1
crc-32: 1.2.2
chalk@2.3.0:
dependencies:
ansi-styles: 3.2.1
@ -11260,7 +11328,9 @@ snapshots:
code-block-writer@12.0.0: {}
collect-v8-coverage@1.0.2: {}
codepage@1.15.0: {}
collect-v8-coverage@1.0.3: {}
color-convert@1.9.3:
dependencies:
@ -11353,6 +11423,8 @@ snapshots:
optionalDependencies:
typescript: 5.7.2
crc-32@1.2.2: {}
cross-env@7.0.3:
dependencies:
cross-spawn: 7.0.6
@ -11884,8 +11956,8 @@ snapshots:
'@typescript-eslint/parser': 7.2.0(eslint@8.57.1)(typescript@5.7.2)
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1)
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
eslint-plugin-react: 7.37.3(eslint@8.57.1)
eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.57.1)
@ -11916,7 +11988,7 @@ snapshots:
is-glob: 4.0.3
stable-hash: 0.0.4
optionalDependencies:
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)
transitivePeerDependencies:
- supports-color
@ -11931,7 +12003,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.7.2))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.2.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.8
@ -12198,6 +12270,8 @@ snapshots:
dependencies:
flat-cache: 3.2.0
file-saver@2.0.5: {}
file-selector@2.1.2:
dependencies:
tslib: 2.8.1
@ -12253,7 +12327,11 @@ snapshots:
dependencies:
fetch-blob: 3.2.0
framer-motion@11.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
forwarded@0.2.0: {}
frac@1.1.2: {}
framer-motion@11.18.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
motion-dom: 11.14.3
motion-utils: 11.14.3
@ -15619,7 +15697,15 @@ snapshots:
sprintf-js@1.0.3: {}
<<<<<<< HEAD
stable-hash@0.0.4: {}
=======
ssf@0.11.2:
dependencies:
frac: 1.1.2
stable-hash@0.0.5: {}
>>>>>>> e5e32496aba520aed62e3a73e9e0bcc42eaca928
stack-utils@2.0.6:
dependencies:
@ -16398,8 +16484,21 @@ snapshots:
dependencies:
isexe: 2.0.0
wmf@1.0.2: {}
word-wrap@1.2.5: {}
<<<<<<< HEAD
=======
word@0.3.0: {}
wrap-ansi@6.2.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
>>>>>>> e5e32496aba520aed62e3a73e9e0bcc42eaca928
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
@ -16423,6 +16522,16 @@ snapshots:
ws@8.18.3: {}
xlsx@0.18.5:
dependencies:
adler-32: 1.3.1
cfb: 1.2.2
codepage: 1.15.0
crc-32: 1.2.2
ssf: 0.11.2
wmf: 1.0.2
word: 0.3.0
xml-name-validator@5.0.0: {}
xmlchars@2.2.0: {}

View File

@ -2,6 +2,7 @@ import api from "@/src/lib/api";
import {
httpGetInterceptor,
httpPostInterceptor,
httpPutInterceptor,
} from "../http-config/http-interceptor-service";
export async function getMediaTrackingMonitoring(page: number, size: number) {
@ -63,31 +64,41 @@ export async function listDataTracking(
);
}
export async function listDataAllNonPagination(search: string) {
return await httpGetInterceptor(
`media/public/list?enablePage=0&sort=desc&title=${search || ""}`
);
}
export const validateMediaLink = async (
resultId: number,
isRelevant: boolean
) => {
try {
const res = await api.put(
"/media/tracking/monitoring/results/relevant",
{
resultId,
isRelevant,
}
);
export async function validateMediaLink(resultId: number, isRelevant: boolean) {
const url = "media/tracking/monitoring/results/relevant";
return res.data;
} catch (error: any) {
throw new Error(
error?.response?.data?.messages?.[0] ||
"Gagal memperbarui status relevansi"
);
}
};
const payload = {
resultId,
isRelevant,
};
return httpPutInterceptor(url, payload);
}
// export const validateMediaLink = async (
// resultId: number,
// isRelevant: boolean
// ) => {
// try {
// const res = await api.put(
// "/media/tracking/monitoring/results/relevant",
// {
// resultId,
// isRelevant,
// }
// );
// return res.data;
// } catch (error: any) {
// throw new Error(
// error?.response?.data?.messages?.[0] ||
// "Gagal memperbarui status relevansi"
// );
// }
// };

View File

@ -4,5 +4,6 @@ import "@tanstack/react-table";
declare module "@tanstack/react-table" {
interface TableMeta<TData> {
updateData: (rowIndex: number, value: Partial<TData>) => void;
refetchData?: () => void;
}
}