-
+ {/*
*/}
diff --git a/components/form/content/audio-visual/video-detail-form.tsx b/components/form/content/audio-visual/video-detail-form.tsx
index c0cdc18..d117b7a 100644
--- a/components/form/content/audio-visual/video-detail-form.tsx
+++ b/components/form/content/audio-visual/video-detail-form.tsx
@@ -1,5 +1,5 @@
"use client";
-import React, { ChangeEvent, useEffect, useRef, useState } from "react";
+import React, { useEffect, useRef, useState } from "react";
import { useForm, Controller } from "react-hook-form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
@@ -18,32 +18,21 @@ import {
SelectValue,
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
-import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
-
-import { register } from "module";
-import { Switch } from "@/components/ui/switch";
import Cookies from "js-cookie";
import {
- createMedia,
+ getArticleDetail,
getTagsBySubCategoryId,
listEnableCategory,
- rejectFiles,
+ publishMedia,
submitApproval,
} from "@/service/content/content";
-import {
- detailMedia,
- getDataApprovalByMediaUpload,
-} from "@/service/curated-content/curated-content";
+import { getDataApprovalByMediaUpload } from "@/service/curated-content/curated-content";
import { Badge } from "@/components/ui/badge";
-import { MailIcon } from "lucide-react";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
-import "swiper/css/free-mode";
import "swiper/css/navigation";
import "swiper/css/pagination";
import "swiper/css/thumbs";
-import "swiper/css";
-import "swiper/css/navigation";
import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules";
import {
DialogHeader,
@@ -53,7 +42,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Textarea } from "@/components/ui/textarea";
-import { loading } from "@/config/swal";
+import { close, loading, successCallback } from "@/config/swal";
import { getCookiesDecrypt } from "@/lib/utils";
import { Icon } from "@iconify/react/dist/iconify.js";
import { error } from "@/lib/swal";
@@ -62,13 +51,14 @@ import SuggestionModal from "@/components/modal/suggestions-modal";
import { formatDateToIndonesian } from "@/utils/globals";
import ApprovalHistoryModal from "@/components/modal/approval-history-modal";
-const imageSchema = z.object({
+const videoSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }),
- description: z
- .string()
- .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }),
+ description: z.string().min(2, { message: "Deskripsi diperlukan" }),
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
- // tags: z.string().min(1, { message: "Judul diperlukan" }),
+});
+
+const ViewEditor = dynamic(() => import("@/components/editor/view-editor"), {
+ ssr: false,
});
type Category = {
@@ -78,193 +68,173 @@ type Category = {
type FileType = {
id: number;
- url: string;
- thumbnailFileUrl: string;
fileName: string;
+ fileUrl?: string;
+ fileThumbnail?: string;
+ format?: string;
};
type Detail = {
- id: string;
+ id: number;
title: string;
description: string;
+ htmlDescription: string;
slug: string;
- category: {
+ categoryId: number;
+ categoryName: string;
+ typeId: number;
+ tags: string;
+ thumbnailUrl: string;
+ pageUrl: string | null;
+ createdById: number;
+ createdByName: string;
+ shareCount: number;
+ viewCount: number;
+ commentCount: number;
+ aiArticleId: number | null;
+ oldId: number;
+ statusId: number;
+ isBanner: boolean;
+ isPublish: boolean;
+ publishedAt: string | null;
+ isActive: boolean;
+ createdAt: string;
+ updatedAt: string;
+ files: FileType[] | null;
+ categories: {
+ id: number;
+ title: string;
+ description: string;
+ thumbnailUrl: string;
+ slug: string | null;
+ tags: string[];
+ thumbnailPath: string | null;
+ parentId: number;
+ oldCategoryId: number | null;
+ createdById: number;
+ statusId: number;
+ isPublish: boolean;
+ publishedAt: string | null;
+ isEnabled: boolean | null;
+ isActive: boolean;
+ createdAt: string;
+ updatedAt: string;
+ }[];
+ // Legacy fields for backward compatibility
+ category?: {
id: number;
name: string;
};
- categoryName: string;
- creatorName: string;
- thumbnailLink: string;
- url: string;
- tags: string;
- statusName: string;
- isPublish: boolean;
- needApprovalFromLevel: number;
- files: FileType[];
- uploadedById: number;
+ creatorName?: string;
+ thumbnailLink?: string;
+ statusName?: string;
+ needApprovalFromLevel?: number;
+ uploadedById?: number;
};
-const ViewEditor = dynamic(
- () => {
- return import("@/components/editor/view-editor");
- },
- { ssr: false }
-);
-
export default function FormVideoDetail() {
const MySwal = withReactContent(Swal);
const router = useRouter();
+ const { id } = useParams() as { id: string };
const userId = getCookiesDecrypt("uie");
const userLevelId = getCookiesDecrypt("ulie");
+ const userLevelName = Cookies.get("state");
const roleId = getCookiesDecrypt("urie");
-
- const [modalOpen, setModalOpen] = useState(false);
- const { id } = useParams() as { id: string };
- console.log(id);
- const editor = useRef(null);
- type ImageSchema = z.infer
;
-
- const [selectedFiles, setSelectedFiles] = useState([]);
- const taskId = Cookies.get("taskId");
- const scheduleId = Cookies.get("scheduleId");
- const scheduleType = Cookies.get("scheduleType");
- const [status, setStatus] = useState("");
+ const [detail, setDetail] = useState(null);
const [categories, setCategories] = useState([]);
- const [selectedCategory, setSelectedCategory] = useState();
- const [tags, setTags] = useState([]);
- const [detail, setDetail] = useState();
- const [refresh, setRefresh] = useState(false);
- const [selectedPublishers, setSelectedPublishers] = useState([]);
- const [description, setDescription] = useState("");
- const [main, setMain] = useState([]);
- const [detailVideo, setDetailVideo] = useState([]);
- const [thumbsSwiper, setThumbsSwiper] = useState(null);
- const [filePlacements, setFilePlacements] = useState([]);
- const [selectedTarget, setSelectedTarget] = useState("");
const [files, setFiles] = useState([]);
- const [rejectedFiles, setRejectedFiles] = useState([]);
- const [isUserMabesApprover, setIsUserMabesApprover] = useState(false);
+ const [thumbsSwiper, setThumbsSwiper] = useState(null);
const [approval, setApproval] = useState();
-
- let fileTypeId = "2";
+ const [selectedPublishers, setSelectedPublishers] = useState([]);
+ const [modalOpen, setModalOpen] = useState(false);
+ const [status, setStatus] = useState("");
+ const [description, setDescription] = useState("");
+ const [filePlacements, setFilePlacements] = useState([]);
+ const [isUserMabesApprover, setIsUserMabesApprover] = useState(false);
+ const [refresh, setRefresh] = useState(false);
+ const [detailVideos, setDetailVideos] = useState([]);
const {
control,
- handleSubmit,
- setValue,
formState: { errors },
- } = useForm({
- resolver: zodResolver(imageSchema),
+ } = useForm({
+ resolver: zodResolver(videoSchema),
});
- // const handleKeyDown = (e: any) => {
- // const newTag = e.target.value.trim(); // Ambil nilai input
- // if (e.key === "Enter" && newTag) {
- // e.preventDefault(); // Hentikan submit form
- // if (!tags.includes(newTag)) {
- // setTags((prevTags) => [...prevTags, newTag]); // Tambah tag baru
- // setValue("tags", ""); // Kosongkan input
- // }
- // }
- // };
+ const getStatusName = (statusId: number): string => {
+ const statusMap: { [key: number]: string } = {
+ 1: "Menunggu Review",
+ 2: "Diterima",
+ 3: "Minta Update",
+ 4: "Ditolak",
+ };
+ return statusMap[statusId] || "Unknown";
+ };
useEffect(() => {
- if (
- userLevelId != undefined &&
- roleId != undefined &&
- userLevelId == "216" &&
- roleId == "3"
- ) {
+ if (userLevelId == "216" && roleId == "3") {
setIsUserMabesApprover(true);
}
}, [userLevelId, roleId]);
+ useEffect(() => {
+ async function fetchCategories() {
+ const categoryRes = await listEnableCategory("2"); // video type
+ setCategories(categoryRes?.data || []);
+ }
+ fetchCategories();
+ }, []);
+
+ useEffect(() => {
+ async function fetchDetail() {
+ if (!id) return;
+ try {
+ const response = await getArticleDetail(Number(id));
+ const details = response?.data?.data;
+
+ const mappedDetail: Detail = {
+ ...details,
+ categoryName:
+ details?.categories?.[0]?.title || details?.categoryName,
+ htmlDescription: details?.htmlDescription,
+ statusName: getStatusName(details?.statusId),
+ uploadedById: details?.createdById,
+ files: details?.files || [],
+ categories: details?.categories || [],
+ };
+
+ const mappedFiles =
+ details?.files?.map((f: any) => ({
+ id: f.id,
+ fileName: f.fileName,
+ fileUrl: f.fileUrl,
+ fileThumbnail: f.fileThumbnail,
+ format: f.format || "mp4",
+ })) || [];
+
+ setDetail(mappedDetail);
+ setFiles(mappedFiles);
+ setDetailVideos(mappedFiles.map((f: any) => f.fileUrl || ""));
+ const approvals = await getDataApprovalByMediaUpload(mappedDetail.id);
+ setApproval(approvals?.data?.data);
+ } catch (err) {
+ console.error("Error fetching video detail:", err);
+ }
+ }
+ fetchDetail();
+ }, [id, refresh]);
+
const handleCheckboxChange = (id: number) => {
setSelectedPublishers((prev) =>
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
);
};
- useEffect(() => {
- async function initState() {
- getCategories();
- }
-
- initState();
- }, []);
-
- const getCategories = async () => {
- try {
- const category = await listEnableCategory(fileTypeId);
- const resCategory: Category[] = category?.data?.data?.content;
-
- setCategories(resCategory);
- console.log("data category", resCategory);
-
- if (scheduleId && scheduleType === "3") {
- const findCategory = resCategory.find((o) =>
- o.name.toLowerCase().includes("pers rilis")
- );
-
- if (findCategory) {
- // setValue("categoryId", findCategory.id);
- setSelectedCategory(findCategory.id);
- const response = await getTagsBySubCategoryId(findCategory.id);
- setTags(response?.data?.data);
- }
- }
- } catch (error) {
- console.error("Failed to fetch categories:", error);
- }
- };
-
- useEffect(() => {
- async function initState() {
- if (id) {
- const response = await detailMedia(id);
- const details = response?.data?.data;
- console.log("detail", details);
- setFiles(details?.files);
- setDetail(details);
- setMain({
- type: details?.fileType.name,
- url: details?.files[0]?.url,
- names: details?.files[0]?.fileName,
- format: details?.files[0]?.format,
- });
-
- if (details?.publishedForObject) {
- const publisherIds = details.publishedForObject.map(
- (obj: any) => obj.id
- );
- setSelectedPublishers(publisherIds);
- }
-
- // Set the selected target to the category ID from details
- setSelectedTarget(String(details.category.id));
-
- const filesData = details?.files || [];
- const fileUrls = filesData.map((files: { url: string }) =>
- files.url ? files.url : "default-image.jpg"
- );
- setDetailVideo(fileUrls);
-
- const approvals = await getDataApprovalByMediaUpload(details?.id);
- setApproval(approvals?.data?.data);
- }
- }
- initState();
- }, [refresh, setValue]);
-
const actionApproval = (e: string) => {
const temp = [];
- for (const element of detail.files) {
- temp.push([]);
- }
+ for (const element of files) temp.push([]);
setFilePlacements(temp);
setStatus(e);
- setFiles(detail.files);
-
setDescription("");
setModalOpen(true);
};
@@ -275,621 +245,1150 @@ export default function FormVideoDetail() {
Number(status) == 2 ||
Number(status) == 4
) {
- save();
-
- // MySwal.fire({
- // title: "Simpan Approval",
- // text: "",
- // icon: "warning",
- // showCancelButton: true,
- // cancelButtonColor: "#d33",
- // confirmButtonColor: "#3085d6",
- // confirmButtonText: "Simpan",
- // }).then((result) => {
- // if (result.isConfirmed) {
- // }
- // });
+ await save();
}
};
- async function save() {
+ const save = async () => {
const data = {
action: status == "2" ? "approve" : status == "3" ? "revision" : "reject",
message: description,
};
-
setModalOpen(false);
loading();
const response = await submitApproval(id, data);
-
- if (response?.error) {
- error(response.message);
- return false;
- }
-
+ if (response?.error) return error(response.message);
close();
- submitApprovalSuccesss();
-
- return false;
- }
-
- const getPlacement = () => {
- console.log("getPlaa", filePlacements);
- const temp = [];
- for (let i = 0; i < filePlacements?.length; i++) {
- if (filePlacements[i].length !== 0) {
- const now = filePlacements[i].filter((a) => a !== "all");
- const data = { mediaFileId: files[i].id, placements: now.join(",") };
- temp.push(data);
- }
- }
- return temp;
- };
-
- const setupPlacement = (
- index: number,
- placement: string,
- checked: boolean
- ) => {
- let temp = [...filePlacements];
- if (checked) {
- if (placement === "all") {
- temp[index] = ["all", "mabes", "polda", "international"];
- } else {
- const now = temp[index];
- now.push(placement);
- if (now.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;
- if (now.length === 3 && now.includes("all")) {
- const newData = now.filter((b) => b !== "all");
- temp[index] = newData;
- }
- }
- }
- setFilePlacements(temp);
- };
-
- function handleDeleteFileApproval(id: number) {
- const selectedFiles = files.filter((file) => file.id != id);
- setFiles(selectedFiles);
- const rejects = rejectedFiles;
- rejects.push(id);
- setRejectedFiles(rejects);
- }
- const handleMain = (
- type: string,
- url: string,
- names: string,
- format: string
- ) => {
- console.log("Test 3 :", type, url, names, format);
- setMain({
- type,
- url,
- names,
- format,
- });
- return false;
- };
-
- const submitApprovalSuccesss = () => {
MySwal.fire({
title: "Sukses",
text: "Data berhasil disimpan.",
icon: "success",
- confirmButtonColor: "#3085d6",
- confirmButtonText: "OK",
- }).then((result) => {
- if (result.isConfirmed) {
- router.push("/admin/content/video");
- }
- });
+ }).then(() => router.push("/admin/content/video"));
};
+ const publishToMabes = async () => {
+ const res = await publishMedia(id);
+ successCallback();
+ };
+
+ if (!detail) {
+ return (
+
+ Memuat detail video...
+
+ );
+ }
+
return (