diff --git a/app/[locale]/(admin)/admin/content/video/update/[id]/page.tsx b/app/[locale]/(admin)/admin/content/video/update/[id]/page.tsx
index e136c95..6a37af7 100644
--- a/app/[locale]/(admin)/admin/content/video/update/[id]/page.tsx
+++ b/app/[locale]/(admin)/admin/content/video/update/[id]/page.tsx
@@ -1,10 +1,11 @@
import FormVideoUpdate from "@/components/form/content/audio-visual/video-update-form";
+import SiteBreadcrumb from "@/components/site-breadcrumb";
const VideoUpdatePage = async () => {
return (
- {/*
*/}
-
diff --git a/components/form/content/audio-visual/video-detail-form.tsx b/components/form/content/audio-visual/video-detail-form.tsx
index b2d4074..e868c0c 100644
--- a/components/form/content/audio-visual/video-detail-form.tsx
+++ b/components/form/content/audio-visual/video-detail-form.tsx
@@ -173,6 +173,7 @@ export default function FormVideoDetail() {
htmlDescription: details?.htmlDescription,
uploadedById: details?.createdById,
files: details?.files || [],
+ thumbnailUrl: details?.thumbnailUrl || details?.thumbnail || "",
};
setDetail(mappedDetail);
setFiles(details?.files || []);
diff --git a/components/form/content/audio-visual/video-form.tsx b/components/form/content/audio-visual/video-form.tsx
index a510b85..e9404c3 100644
--- a/components/form/content/audio-visual/video-form.tsx
+++ b/components/form/content/audio-visual/video-form.tsx
@@ -1,298 +1,3 @@
-"use client";
-import React, {
- ChangeEvent,
- useEffect,
- useRef,
- Fragment,
- useState,
-} from "react";
-import { useForm, Controller } from "react-hook-form";
-import { Input } from "@/components/ui/input";
-import { Button } from "@/components/ui/button";
-import { Label } from "@/components/ui/label";
-import { Card } from "@/components/ui/card";
-import { zodResolver } from "@hookform/resolvers/zod";
-import * as z from "zod";
-import { useDropzone } from "react-dropzone";
-import Swal from "sweetalert2";
-import withReactContent from "sweetalert2-react-content";
-import { useParams, useRouter } from "next/navigation";
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select";
-import { Checkbox } from "@/components/ui/checkbox";
-import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
-import { Switch } from "@/components/ui/switch";
-import Cookies from "js-cookie";
-import Image from "next/image";
-import dynamic from "next/dynamic";
-import { CloudUpload } from "lucide-react";
-import { toast } from "sonner";
-import { htmlToString } from "@/utils/globals";
-import { getCookiesDecrypt } from "@/lib/utils";
-import { getCsrfToken } from "@/service/auth";
-import {
- createArticle,
- uploadArticleFiles,
- uploadArticleThumbnail,
- listArticleCategories,
- listEnableCategory,
- getTagsBySubCategoryId,
- CreateArticleData,
-} from "@/service/content/content";
-import {
- generateDataArticle,
- generateDataRewrite,
- getGenerateKeywords,
- getGenerateTitle,
- getDetailArticle,
-} from "@/service/content/ai";
-
-const CustomEditor = dynamic(
- () => import("@/components/editor/custom-editor"),
- { ssr: false }
-);
-
-interface FileWithPreview extends File {
- preview: string;
-}
-
-export default function FormVideo() {
- const MySwal = withReactContent(Swal);
- const router = useRouter();
- const params = useParams();
- const roleId = getCookiesDecrypt("urie");
- const userId = Cookies.get("userId");
- const [files, setFiles] = useState
([]);
- const [fileError, setFileError] = useState(null);
- const [publishedFor, setPublishedFor] = useState([]);
- const [title, setTitle] = useState("");
- const [categories, setCategories] = useState([]);
- const [selectedCategory, setSelectedCategory] = useState();
- const [preview, setPreview] = useState(null);
- const [thumbnail, setThumbnail] = useState(null);
- const [isSwitchOn, setIsSwitchOn] = useState(false);
- const [selectedFileType, setSelectedFileType] = useState("original");
- const [editorContent, setEditorContent] = useState("");
- const [rewriteEditorContent, setRewriteEditorContent] = useState("");
- const [isLoading, setIsLoading] = useState(false);
- const [articleBody, setArticleBody] = useState("");
- const [showRewriteEditor, setShowRewriteEditor] = useState(false);
- const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
- const [articleIds, setArticleIds] = useState([]);
- const [selectedArticleId, setSelectedArticleId] = useState(
- null
- );
- const [isLoadingData, setIsLoadingData] = useState(false);
- const [tags, setTags] = useState([]);
- const inputRef = useRef(null);
-
- // --- SCHEMA & FORM SETUP ---
- const videoSchema = z.object({
- title: z.string().min(1, { message: "Judul wajib diisi." }),
- description: z.string().optional(),
- descriptionOri: z.string().optional(),
- rewriteDescription: z.string().optional(),
- creatorName: z.string().min(1, { message: "Nama pembuat wajib diisi." }),
- files: z
- .array(z.any())
- .min(1, { message: "Minimal 1 file harus diunggah." }),
- categoryId: z.string().min(1, { message: "Kategori wajib dipilih." }),
- tags: z
- .array(z.string())
- .min(1, { message: "Minimal 1 tag harus ditambahkan." }),
- publishedFor: z
- .array(z.string())
- .min(1, { message: "Minimal 1 target publish harus dipilih." }),
- });
-
- const {
- control,
- handleSubmit,
- getValues,
- setValue,
- formState: { errors },
- } = useForm>({
- resolver: zodResolver(videoSchema),
- defaultValues: {
- title: "",
- description: "",
- descriptionOri: "",
- rewriteDescription: "",
- creatorName: "",
- files: [],
- categoryId: "",
- tags: [],
- publishedFor: [],
- },
- });
-
- // --- FIX ① setValue hanya jalan saat publishedFor berubah setelah form siap ---
- useEffect(() => {
- if (publishedFor && publishedFor.length > 0) {
- setValue("publishedFor", publishedFor);
- }
- }, [publishedFor, setValue]);
-
- // --- FIX ② pindahkan setValue("files") ke useEffect ---
- useEffect(() => {
- if (files.length > 0) {
- setValue("files", files, { shouldValidate: true });
- }
- }, [files, setValue]);
-
- // --- FIX ③ setValue("title") hanya jalan setelah form mount ---
- useEffect(() => {
- const formReady = getValues("title") !== undefined;
- if (formReady && !getValues("title") && title) {
- setValue("title", title);
- }
- }, [title, getValues, setValue]);
-
- // --- DROPZONE HANDLER aman ---
- const { getRootProps, getInputProps } = useDropzone({
- accept: { "video/mp4": [".mp4"], "video/quicktime": [".mov"] },
- maxSize: 500 * 1024 * 1024,
- multiple: true,
- onDrop: (acceptedFiles, fileRejections) => {
- setFileError(null);
- if (fileRejections.length > 0) {
- const messages = fileRejections
- .map((rej) => rej.errors.map((e) => e.message).join(", "))
- .join(", ");
- setFileError(messages || "File tidak valid");
- return;
- }
- if (acceptedFiles.length === 0) {
- setFileError("Wajib upload minimal 1 file video");
- return;
- }
- const filesWithPreview = acceptedFiles.map((file) =>
- Object.assign(file, { preview: URL.createObjectURL(file) })
- );
- setFiles((prev) => [...prev, ...filesWithPreview]); // ⛔ Tidak lagi ada setValue di sini
- },
- });
-
- // --- FETCH CATEGORY AMAN ---
- useEffect(() => {
- const getCategories = async () => {
- try {
- const category = await listArticleCategories(1, 100);
- if (!category?.error) {
- const mapped =
- category?.data?.data?.map((item: any) => ({
- id: item.id,
- name: item.title,
- })) || [];
- setCategories(mapped);
- } else {
- const fallback = await listEnableCategory("2");
- setCategories(fallback?.data?.data?.content || []);
- }
- } catch (err) {
- console.error("Error fetching category:", err);
- }
- };
- getCategories();
- }, []);
-
- // --- THUMBNAIL PREVIEW CLEANUP ---
- useEffect(() => {
- return () => {
- if (preview) URL.revokeObjectURL(preview);
- };
- }, [preview]);
-
- // --- FORM SUBMIT ---
- const onSubmit = (data: z.infer) => {
- MySwal.fire({
- title: "Simpan Data",
- text: "Apakah Anda yakin ingin menyimpan data ini?",
- icon: "warning",
- showCancelButton: true,
- confirmButtonText: "Simpan",
- cancelButtonText: "Batal",
- }).then((result) => {
- if (result.isConfirmed) save(data);
- });
- };
-
- // --- SIMULASI SAVE ---
- async function save(data: z.infer) {
- console.log("✅ Data tersimpan:", data);
- toast.success("Data berhasil disimpan!");
- }
-
- // --- RENDER ---
- return (
-
- );
-}
-
// "use client";
// import React, {
// ChangeEvent,
@@ -308,10 +13,10 @@ export default function FormVideo() {
// import { Card } from "@/components/ui/card";
// import { zodResolver } from "@hookform/resolvers/zod";
// import * as z from "zod";
-// import { Upload } from "tus-js-client";
+// import { useDropzone } from "react-dropzone";
// import Swal from "sweetalert2";
// import withReactContent from "sweetalert2-react-content";
-// import { redirect, useParams, useRouter } from "next/navigation";
+// import { useParams, useRouter } from "next/navigation";
// import {
// Select,
// SelectContent,
@@ -321,47 +26,34 @@ export default function FormVideo() {
// } from "@/components/ui/select";
// import { Checkbox } from "@/components/ui/checkbox";
// import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
-
// import { Switch } from "@/components/ui/switch";
// import Cookies from "js-cookie";
-
-// import { Textarea } from "@/components/ui/textarea";
-// import { getCookiesDecrypt } from "@/lib/utils";
-// import { useDropzone } from "react-dropzone";
-// import { Icon } from "@iconify/react";
-// import { CloudUpload } from "lucide-react";
// import Image from "next/image";
-// import { error, loading } from "@/config/swal";
-// import { Item } from "@radix-ui/react-dropdown-menu";
// import dynamic from "next/dynamic";
-// import { getCsrfToken } from "@/service/auth";
-// import {
-// createMedia,
-// createArticle,
-// getTagsBySubCategoryId,
-// listEnableCategory,
-// listArticleCategories,
-// uploadThumbnail,
-// uploadArticleFiles,
-// uploadArticleThumbnail,
-// CreateArticleData,
-// } from "@/service/content/content";
-// import { request } from "http";
+// import { CloudUpload } from "lucide-react";
// import { toast } from "sonner";
// import { htmlToString } from "@/utils/globals";
+// import { getCookiesDecrypt } from "@/lib/utils";
+// import { getCsrfToken } from "@/service/auth";
+// import {
+// createArticle,
+// uploadArticleFiles,
+// uploadArticleThumbnail,
+// listArticleCategories,
+// listEnableCategory,
+// getTagsBySubCategoryId,
+// CreateArticleData,
+// } from "@/service/content/content";
// import {
// generateDataArticle,
// generateDataRewrite,
-// getDetailArticle,
// getGenerateKeywords,
// getGenerateTitle,
+// getDetailArticle,
// } from "@/service/content/ai";
-// import Link from "next/link";
// const CustomEditor = dynamic(
-// () => {
-// return import("@/components/editor/custom-editor");
-// },
+// () => import("@/components/editor/custom-editor"),
// { ssr: false }
// );
@@ -369,147 +61,46 @@ export default function FormVideo() {
// preview: string;
// }
-// type Category = {
-// id: string;
-// name: string;
-// };
-
-// type Option = {
-// id: string;
-// label: string;
-// };
-
// export default function FormVideo() {
// const MySwal = withReactContent(Swal);
// const router = useRouter();
-// const editor = useRef(null);
-// type VideoSchema = z.infer;
// const params = useParams();
-// const locale = params?.locale;
-// const [selectedFiles, setSelectedFiles] = useState([]);
-// const taskId = Cookies.get("taskId");
-// const scheduleId = Cookies.get("scheduleId");
-// const scheduleType = Cookies.get("scheduleType");
// const roleId = getCookiesDecrypt("urie");
-// const [selectedFileType, setSelectedFileType] = useState("original");
-// const [categories, setCategories] = useState([]);
+// const userId = Cookies.get("userId");
+// const [files, setFiles] = useState([]);
+// const [fileError, setFileError] = useState(null);
+// const [publishedFor, setPublishedFor] = useState([]);
+// const [title, setTitle] = useState("");
+// const [categories, setCategories] = useState([]);
// const [selectedCategory, setSelectedCategory] = useState();
-// const [tags, setTags] = useState([]);
-// const [thumbnail, setThumbnail] = useState(null);
// const [preview, setPreview] = useState(null);
-// const [selectedLanguage, setSelectedLanguage] = useState("");
-// const [selectedWritingStyle, setSelectedWritingStyle] =
-// useState("professional");
+// const [thumbnail, setThumbnail] = useState(null);
+// const [isSwitchOn, setIsSwitchOn] = useState(false);
+// const [selectedFileType, setSelectedFileType] = useState("original");
// const [editorContent, setEditorContent] = useState("");
// const [rewriteEditorContent, setRewriteEditorContent] = useState("");
-// const [selectedSEO, setSelectedSEO] = useState("");
-// const [title, setTitle] = useState("");
-// const [selectedAdvConfig, setSelectedAdvConfig] = useState("");
-// const [editingArticleId, setEditingArticleId] = useState(null);
-// const [isLoading, setIsLoading] = useState(false);
-// const [isLoadingData, setIsLoadingData] = useState(false);
-// const [articleIds, setArticleIds] = useState([]);
+// const [isLoading, setIsLoading] = useState(false);
+// const [articleBody, setArticleBody] = useState("");
+// const [showRewriteEditor, setShowRewriteEditor] = useState(false);
// const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
-// const [articleBody, setArticleBody] = useState("");
+// const [articleIds, setArticleIds] = useState([]);
// const [selectedArticleId, setSelectedArticleId] = useState(
// null
// );
-// const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
-// const [publishedForError, setPublishedForError] = useState(
-// null
-// );
-// const userId = Cookies.get("userId");
-// const [selectedSize, setSelectedSize] = useState("");
-// const [detailData, setDetailData] = useState(null);
-// const [articleImages, setArticleImages] = useState([]);
-// const [isSwitchOn, setIsSwitchOn] = useState(false);
+// const [isLoadingData, setIsLoadingData] = useState(false);
+// const [tags, setTags] = useState([]);
// const inputRef = useRef(null);
-// const [fileError, setFileError] = useState(null);
-// const [showRewriteEditor, setShowRewriteEditor] = useState(false);
-// const [isContentRewriteClicked, setIsContentRewriteClicked] = useState(false);
-// const [selectedTarget, setSelectedTarget] = useState("");
-// const [unitSelection, setUnitSelection] = useState({
-// allUnit: false,
-// mabes: false,
-// polda: false,
-// polres: false,
-// });
-
-// let fileTypeId = "2";
-// let progressInfo: any = [];
-// let counterUpdateProgress = 0;
-// const [progressList, setProgressList] = useState([]);
-// let uploadPersen = 0;
-// const [isStartUpload, setIsStartUpload] = useState(false);
-// const [counterProgress, setCounterProgress] = useState(0);
-// const [publishedFor, setPublishedFor] = useState([]);
-// const [files, setFiles] = useState([]);
-
-// const options: Option[] = [
-// { id: "all", label: "SEMUA" },
-// { id: "4", label: "UMUM" },
-// { id: "5", label: "JOURNALIS" },
-// ];
-
-// const MAX_FILE_SIZE = 100 * 1024 * 1024;
-// const ACCEPTED_FILE_TYPES = ["video/mp4", "video/quicktime"];
-
-// const { getRootProps, getInputProps } = useDropzone({
-// accept: {
-// "video/mp4": [".mp4"],
-// "video/quicktime": [".mov"],
-// },
-// maxSize: 500 * 1024 * 1024,
-// multiple: true,
-// onDrop: (acceptedFiles, fileRejections) => {
-// setFileError(null);
-
-// if (fileRejections.length > 0) {
-// const messages = fileRejections
-// .map((rej) => rej.errors.map((e) => e.message).join(", "))
-// .join(", ");
-// setFileError(messages || "File tidak valid");
-// return;
-// }
-
-// if (acceptedFiles.length === 0) {
-// setFileError("Wajib upload minimal 1 file video");
-// return;
-// }
-
-// const filesWithPreview = acceptedFiles.map((file) =>
-// Object.assign(file, { preview: URL.createObjectURL(file) })
-// );
-
-// setFiles((prev) => {
-// const updatedFiles = [...prev, ...filesWithPreview];
-// setValue("files", updatedFiles, { shouldValidate: true });
-// return updatedFiles;
-// });
-// },
-// });
+// // --- SCHEMA & FORM SETUP ---
// const videoSchema = z.object({
-// title: z.string().min(1, { message: "titleRequired" }),
+// title: z.string().min(1, { message: "Judul wajib diisi." }),
// description: z.string().optional(),
// descriptionOri: z.string().optional(),
// rewriteDescription: z.string().optional(),
-// creatorName: z.string().min(1, { message: "creatorRequired" }),
+// creatorName: z.string().min(1, { message: "Nama pembuat wajib diisi." }),
// files: z
// .array(z.any())
-// .min(1, { message: "Minimal 1 file harus diunggah." })
-// .refine(
-// (files) =>
-// files.every(
-// (file: File) =>
-// ["video/mp4", "video/mov", "video/avi"].includes(file.type) &&
-// file.size <= 100 * 1024 * 1024
-// ),
-// {
-// message:
-// "Hanya file .mp4, .mov, .avi, maksimal 100MB yang diperbolehkan.",
-// }
-// ),
+// .min(1, { message: "Minimal 1 file harus diunggah." }),
// categoryId: z.string().min(1, { message: "Kategori wajib dipilih." }),
// tags: z
// .array(z.string())
@@ -540,1385 +131,1790 @@ export default function FormVideo() {
// },
// });
+// // --- FIX ① setValue hanya jalan saat publishedFor berubah setelah form siap ---
// useEffect(() => {
-// setValue("publishedFor", publishedFor);
+// if (publishedFor && publishedFor.length > 0) {
+// setValue("publishedFor", publishedFor);
+// }
// }, [publishedFor, setValue]);
-// const doGenerateMainKeyword = async () => {
-// console.log(selectedMainKeyword);
-// if (selectedMainKeyword?.length > 1) {
-// try {
-// setIsLoading(true);
-// const titleData = {
-// keyword: selectedMainKeyword,
-// style: selectedWritingStyle,
-// website: "0",
-// connectToWeb: true,
-// lang: selectedLanguage,
-// pointOfView: "None",
-// clientId: "",
-// };
-// console.log("Sending request for title with data:", titleData);
-// const titleRes = await getGenerateTitle(titleData);
-// setTitle(titleRes?.data?.data || "");
-// console.log("Generated title:", titleRes?.data?.data);
-
-// const keywordsData = {
-// keyword: selectedMainKeyword,
-// style: selectedWritingStyle,
-// website: "0",
-// connectToWeb: true,
-// lang: selectedLanguage,
-// pointOfView: "None",
-// clientId: "",
-// };
-// console.log("Sending request for keywords with data:", keywordsData);
-// const keywordsRes = await getGenerateKeywords(keywordsData);
-// setSelectedSEO(keywordsRes?.data?.data || []);
-// console.log("Generated keywords:", keywordsRes?.data?.data);
-// } catch (error) {
-// console.error("Error during generation process:", error);
-// } finally {
-// setIsLoading(false);
-// }
-// } else {
-// Swal.fire({
-// icon: "warning",
-// title: "WARNING",
-// text: "Please provide a valid main keyword.",
-// });
-// console.error("Please provide a valid main keyword.");
-// }
-// };
-
-// const doGenerateTitle = async () => {
-// if (selectedMainKeyword?.length > 1) {
-// try {
-// setIsLoading(true);
-// const titleData = {
-// keyword: selectedMainKeyword,
-// style: selectedWritingStyle,
-// website: "0",
-// connectToWeb: true,
-// lang: selectedLanguage,
-// pointOfView: "None",
-// clientId: "",
-// };
-// console.log("Sending request for title with data:", titleData);
-// const titleRes = await getGenerateTitle(titleData);
-// setTitle(titleRes?.data?.data || "");
-// console.log("Generated title:", titleRes?.data?.data);
-// } catch (error) {
-// console.error("Error generating title:", error);
-// } finally {
-// setIsLoading(false);
-// }
-// } else {
-// Swal.fire({
-// icon: "warning",
-// title: "WARNING",
-// text: "Please provide a valid title.",
-// });
-// console.error("Please provide a valid main keyword.");
-// }
-// };
-
-// const doGenerateKeyword = async () => {
-// if (selectedMainKeyword?.length > 1) {
-// try {
-// setIsLoading(true);
-// const keywordsData = {
-// keyword: selectedMainKeyword,
-// style: selectedWritingStyle,
-// website: "0",
-// connectToWeb: true,
-// lang: selectedLanguage,
-// pointOfView: "None",
-// clientId: "",
-// };
-// console.log("Sending request for keywords with data:", keywordsData);
-// const keywordsRes = await getGenerateKeywords(keywordsData);
-// setSelectedSEO(keywordsRes?.data?.data || []);
-// console.log("Generated keywords:", keywordsRes?.data?.data);
-// } catch (error) {
-// console.error("Error generating keywords:", error);
-// } finally {
-// setIsLoading(false);
-// }
-// } else {
-// Swal.fire({
-// icon: "warning",
-// title: "WARNING",
-// text: "Please provide a valid keyword.",
-// });
-// console.error("Please provide a valid main keyword.");
-// }
-// };
-
-// const handleGenerateArtikel = async () => {
-// const request = {
-// advConfig: selectedAdvConfig,
-// style: selectedWritingStyle,
-// website: "None",
-// connectToWeb: true,
-// lang: selectedLanguage,
-// pointOfView: "None",
-// title: title,
-// imageSource: "Web",
-// mainKeyword: selectedMainKeyword,
-// additionalKeywords: selectedSEO,
-// targetCountry: null,
-// articleSize: selectedSize,
-// projectId: 2,
-// createdBy: roleId,
-// clientId: "ngDLPPiorplznw2jTqVe3YFCz5xqKfUJ",
-// };
-
-// const res = await generateDataArticle(request);
-// close();
-
-// if (res?.error) {
-// console.error(res.message);
-// return false;
-// }
-
-// const newArticleId = res?.data?.data?.id;
-// setIsGeneratedArticle(true);
-
-// setArticleIds((prevIds: string[]) => {
-// if (prevIds.length < 3) {
-// return [...prevIds, newArticleId];
-// } else {
-// const updatedIds = [...prevIds];
-// updatedIds[2] = newArticleId;
-// return updatedIds;
-// }
-// });
-
-// Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds));
-// };
-
-// const handleArticleIdClick = async (id: string) => {
-// setIsLoadingData(true);
-// let retryCount = 0;
-// const maxRetries = 20;
-
-// try {
-// const waitForStatusUpdate = async () => {
-// while (retryCount < maxRetries) {
-// const res = await getDetailArticle(id);
-// const articleData = res?.data?.data;
-
-// if (articleData?.status === 2) {
-// return articleData;
-// }
-
-// retryCount++;
-// await new Promise((resolve) => setTimeout(resolve, 5000));
-// }
-
-// throw new Error("Timeout: Artikel belum selesai diproses.");
-// };
-// const articleData = await waitForStatusUpdate();
-// const cleanArticleBody = articleData?.articleBody?.replace(
-// /
]*>/g,
-// ""
-// );
-// const articleImagesData = articleData?.imagesUrl?.split(",");
-// setArticleBody(cleanArticleBody || "");
-// setDetailData(articleData);
-// setSelectedArticleId(id);
-// setArticleImages(articleImagesData || []);
-// } catch (error) {
-// console.error("Error fetching article details:", error);
-// } finally {
-// setIsLoadingData(false);
-// }
-// };
-
-// const handleAddTag = (e: React.KeyboardEvent) => {
-// if (e.key === "Enter" && e.currentTarget.value.trim()) {
-// e.preventDefault();
-// const newTag = e.currentTarget.value.trim();
-// if (!tags.includes(newTag)) {
-// setTags((prevTags) => [...prevTags, newTag]);
-// if (inputRef.current) {
-// inputRef.current.value = "";
-// }
-// }
-// }
-// };
-
-// const handleRemoveTag = (index: number) => {
-// setTags((prevTags) => prevTags.filter((_, i) => i !== index));
-// };
-
-// const handleRemoveImage = (index: number) => {
-// setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index));
-// };
-
+// // --- FIX ② pindahkan setValue("files") ke useEffect ---
// useEffect(() => {
-// async function initState() {
-// getCategories();
-// // setVideoActive(fileTypeId == '2');
-// // getRoles();
+// if (files.length > 0) {
+// setValue("files", files, { shouldValidate: true });
// }
+// }, [files, setValue]);
-// initState();
-// }, []);
+// // --- FIX ③ setValue("title") hanya jalan setelah form mount ---
+// useEffect(() => {
+// const formReady = getValues("title") !== undefined;
+// if (formReady && !getValues("title") && title) {
+// setValue("title", title);
+// }
+// }, [title, getValues, setValue]);
-// const getCategories = async () => {
-// try {
-// // Use new Article Categories API
-// const category = await listArticleCategories(1, 100);
-// console.log("Article categories response:", category);
-
-// if (category?.error) {
-// console.error("Failed to fetch article categories:", category.message);
-// // Fallback to old API if new one fails
-// const fallbackCategory = await listEnableCategory(fileTypeId);
-// const resCategory: Category[] =
-// fallbackCategory?.data.data.content || [];
-// setCategories(resCategory);
+// // --- DROPZONE HANDLER aman ---
+// const { getRootProps, getInputProps } = useDropzone({
+// accept: { "video/mp4": [".mp4"], "video/quicktime": [".mov"] },
+// maxSize: 500 * 1024 * 1024,
+// multiple: true,
+// onDrop: (acceptedFiles, fileRejections) => {
+// setFileError(null);
+// if (fileRejections.length > 0) {
+// const messages = fileRejections
+// .map((rej) => rej.errors.map((e) => e.message).join(", "))
+// .join(", ");
+// setFileError(messages || "File tidak valid");
// return;
// }
-
-// // Handle new API response structure
-// const resCategory: Category[] =
-// category?.data?.data?.map((item: any) => ({
-// id: item.id,
-// name: item.title, // map title to name for backward compatibility
-// title: item.title,
-// description: item.description,
-// ...item,
-// })) || [];
-
-// setCategories(resCategory);
-// console.log("Article categories loaded:", resCategory);
-
-// if (scheduleId && scheduleType === "3") {
-// const findCategory = resCategory.find((o) =>
-// o.name.toLowerCase().includes("pers rilis")
-// );
-
-// if (findCategory) {
-// setSelectedCategory(findCategory.id);
-// const response = await getTagsBySubCategoryId(findCategory.id);
-// setTags(response?.data?.data);
-// }
+// if (acceptedFiles.length === 0) {
+// setFileError("Wajib upload minimal 1 file video");
+// return;
// }
-// } catch (error) {
-// console.error("Failed to fetch categories:", error);
-// // Fallback to old API if error occurs
-// try {
-// const fallbackCategory = await listEnableCategory(fileTypeId);
-// const resCategory: Category[] =
-// fallbackCategory?.data.data.content || [];
-// setCategories(resCategory);
-// } catch (fallbackError) {
-// console.error("Fallback category fetch also failed:", fallbackError);
-// }
-// }
-// };
-
-// const handleCheckboxChange = (id: string): void => {
-// if (id === "all") {
-// if (publishedFor.includes("all")) {
-// setPublishedFor([]);
-// } else {
-// setPublishedFor(
-// options
-// .filter((opt: any) => opt.id !== "all")
-// .map((opt: any) => opt.id)
-// );
-// }
-// } else {
-// const updatedPublishedFor = publishedFor.includes(id)
-// ? publishedFor.filter((item) => item !== id)
-// : [...publishedFor, id];
-
-// if (publishedFor.includes("all") && id !== "all") {
-// setPublishedFor(updatedPublishedFor.filter((item) => item !== "all"));
-// } else {
-// setPublishedFor(updatedPublishedFor);
-// }
-// }
-// };
-
-// useEffect(() => {
-// if (articleBody) {
-// setValue("description", articleBody);
-// setValue("rewriteDescription", articleBody);
-// }
-// }, [articleBody, setValue]);
-
-// const save = async (data: VideoSchema) => {
-// if (publishedFor.length === 0) {
-// setPublishedForError("Minimal 1 target publish harus dipilih.");
-// return;
-// } else {
-// setPublishedForError(null);
-// }
-// loading();
-// const finalTags = data.tags.join(", ");
-// const finalTitle = isSwitchOn ? title : data.title;
-// // const finalDescription = articleBody || data.description;
-// const finalDescription = isSwitchOn
-// ? data.description
-// : selectedFileType === "rewrite"
-// ? data.rewriteDescription
-// : data.descriptionOri;
-
-// if (!finalDescription?.trim()) {
-// MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
-// return;
-// }
-
-// function formatDateForBackend(date: Date) {
-// const pad = (n: number) => (n < 10 ? "0" + n : n);
-// return (
-// date.getFullYear() +
-// "-" +
-// pad(date.getMonth() + 1) +
-// "-" +
-// pad(date.getDate()) +
-// " " +
-// pad(date.getHours()) +
-// ":" +
-// pad(date.getMinutes()) +
-// ":" +
-// pad(date.getSeconds())
+// const filesWithPreview = acceptedFiles.map((file) =>
+// Object.assign(file, { preview: URL.createObjectURL(file) })
// );
-// }
-
-// let requestData: {
-// title: string;
-// description: string;
-// htmlDescription: string;
-// fileTypeId: string;
-// categoryId: any;
-// subCategoryId: any;
-// uploadedBy: string;
-// statusId: string;
-// publishedFor: string;
-// creatorName: string;
-// tags: string;
-// isYoutube: boolean;
-// isInternationalMedia: boolean;
-// attachFromScheduleId?: number;
-// } = {
-// ...data,
-// title: finalTitle,
-// description: htmlToString(finalDescription),
-// htmlDescription: finalDescription,
-// fileTypeId,
-// categoryId: selectedCategory,
-// subCategoryId: selectedCategory,
-// uploadedBy: "2b7c8d83-d298-4b19-9f74-b07924506b58",
-// statusId: "1",
-// publishedFor: publishedFor.join(","),
-// creatorName: data.creatorName,
-// tags: finalTags,
-// isYoutube: false,
-// isInternationalMedia: false,
-// };
-
-// let id = Cookies.get("idCreate");
-
-// if (scheduleId !== undefined) {
-// requestData.attachFromScheduleId = Number(scheduleId);
-// }
-
-// if (id == undefined) {
-// // New Articles API request data structure
-// const articleData: CreateArticleData = {
-// aiArticleId: 0, // default 0
-// categoryIds: selectedCategory.toString(),
-// createdAt: formatDateForBackend(new Date()), // ✅ format sesuai backend
-// createdById: Number(userId), // isi dengan userId valid
-// description: htmlToString(finalDescription),
-// htmlDescription: finalDescription,
-// isDraft: true,
-// isPublish: false,
-// oldId: 0,
-// slug: finalTitle
-// .toLowerCase()
-// .replace(/\s+/g, "-")
-// .replace(/[^a-z0-9-]/g, ""),
-// tags: finalTags,
-// title: finalTitle,
-// typeId: 2,
-// };
-
-// // Use new Articles API
-// const response = await createArticle(articleData);
-// console.log("Article Data Submitted:", articleData);
-// console.log("Article API Response:", response);
-
-// if (response?.error) {
-// MySwal.fire(
-// "Error",
-// response.message || "Failed to create article",
-// "error"
-// );
-// return false;
-// }
-
-// // Get the article ID from the new API response
-// const articleId = response?.data?.data?.id;
-// Cookies.set("idCreate", articleId, { expires: 1 });
-// id = articleId;
-
-// // Upload files using new article-files API
-// const formData = new FormData();
-
-// // Add all files to FormData
-// files.forEach((file, index) => {
-// formData.append("files", file);
-// });
-
-// console.log("Uploading files to article:", articleId);
-// console.log("Files to upload:", files.length);
+// setFiles((prev) => [...prev, ...filesWithPreview]); // ⛔ Tidak lagi ada setValue di sini
+// },
+// });
+// // --- FETCH CATEGORY AMAN ---
+// useEffect(() => {
+// const getCategories = async () => {
// try {
-// const uploadResponse = await uploadArticleFiles(articleId, formData);
-
-// if (uploadResponse?.error) {
-// MySwal.fire(
-// "Error",
-// uploadResponse.message || "Failed to upload files",
-// "error"
-// );
-// return false;
+// const category = await listArticleCategories(1, 100);
+// if (!category?.error) {
+// const mapped =
+// category?.data?.data?.map((item: any) => ({
+// id: item.id,
+// name: item.title,
+// })) || [];
+// setCategories(mapped);
+// } else {
+// const fallback = await listEnableCategory("2");
+// setCategories(fallback?.data?.data?.content || []);
// }
-
-// console.log("Files uploaded successfully:", uploadResponse);
-
-// // Upload thumbnail using first file as thumbnail
-// if (files.length > 0) {
-// const thumbnailFormData = new FormData();
-// thumbnailFormData.append("files", files[0]); // Use first file as thumbnail
-
-// console.log("Uploading thumbnail for article:", articleId);
-
-// try {
-// const thumbnailResponse = await uploadArticleThumbnail(
-// articleId,
-// thumbnailFormData
-// );
-
-// if (thumbnailResponse?.error) {
-// console.warn(
-// "Thumbnail upload failed:",
-// thumbnailResponse.message
-// );
-// // Don't fail the whole process if thumbnail upload fails
-// } else {
-// console.log(
-// "Thumbnail uploaded successfully:",
-// thumbnailResponse
-// );
-// }
-// } catch (thumbnailError) {
-// console.warn("Thumbnail upload error:", thumbnailError);
-// // Don't fail the whole process if thumbnail upload fails
-// }
-// }
-// } catch (uploadError) {
-// console.error("Upload error:", uploadError);
-// MySwal.fire(
-// "Error",
-// "Failed to upload files. Please try again.",
-// "error"
-// );
-// return false;
+// } catch (err) {
+// console.error("Error fetching category:", err);
// }
+// };
+// getCategories();
+// }, []);
-// // Show success message
-// MySwal.fire({
-// title: "Sukses",
-// text: "Article dan files berhasil disimpan.",
-// icon: "success",
-// confirmButtonColor: "#3085d6",
-// confirmButtonText: "OK",
-// }).then(() => {
-// router.push("/admin/content/video");
-// });
-
-// Cookies.remove("idCreate");
-// return;
-// }
-
-// Cookies.remove("idCreate");
-// };
-
+// // --- THUMBNAIL PREVIEW CLEANUP ---
// useEffect(() => {
// return () => {
-// if (preview) {
-// URL.revokeObjectURL(preview);
-// }
+// if (preview) URL.revokeObjectURL(preview);
// };
// }, [preview]);
-// const onSubmit = (data: VideoSchema) => {
+// // --- FORM SUBMIT ---
+// const onSubmit = (data: z.infer) => {
// MySwal.fire({
// title: "Simpan Data",
// text: "Apakah Anda yakin ingin menyimpan data ini?",
// icon: "warning",
// showCancelButton: true,
-// cancelButtonColor: "#d33",
-// confirmButtonColor: "#3085d6",
// confirmButtonText: "Simpan",
+// cancelButtonText: "Batal",
// }).then((result) => {
-// if (result.isConfirmed) {
-// save(data);
-// }
+// if (result.isConfirmed) save(data);
// });
// };
-// async function uploadResumableFile(
-// idx: number,
-// id: string,
-// file: any,
-// duration: string
-// ) {
-// console.log(idx, id, file, duration);
-
-// // const placements = getPlacement(file.placements);
-// // console.log("Placementttt: : ", placements);
-// const resCsrf = await getCsrfToken();
-// const csrfToken = resCsrf?.data?.token;
-// console.log("CSRF TOKEN : ", csrfToken);
-// const headers = {
-// "X-XSRF-TOKEN": csrfToken,
-// };
-
-// const upload = new Upload(file, {
-// endpoint: `${process.env.NEXT_PUBLIC_API}/media/file/upload`,
-// headers: headers,
-// retryDelays: [0, 3000, 6000, 12_000, 24_000],
-// chunkSize: 20_000,
-// metadata: {
-// mediaid: id,
-// filename: file.name,
-// filetype: file.type,
-// duration,
-// isWatermark: "true", // hardcode
-// },
-// onBeforeRequest: function (req) {
-// var xhr = req.getUnderlyingObject();
-// xhr.withCredentials = true;
-// },
-// onError: async (e: any) => {
-// console.log("Error upload :", e);
-// error(e);
-// },
-// onChunkComplete: (
-// chunkSize: any,
-// bytesAccepted: any,
-// bytesTotal: any
-// ) => {
-// const uploadPersen = Math.floor((bytesAccepted / bytesTotal) * 100);
-// progressInfo[idx].percentage = uploadPersen;
-// counterUpdateProgress++;
-// console.log(counterUpdateProgress);
-// setProgressList(progressInfo);
-// setCounterProgress(counterUpdateProgress);
-// },
-// onSuccess: async () => {
-// uploadPersen = 100;
-// progressInfo[idx].percentage = 100;
-// counterUpdateProgress++;
-// setCounterProgress(counterUpdateProgress);
-// successTodo();
-// },
-// });
-
-// upload.start();
+// // --- SIMULASI SAVE ---
+// async function save(data: z.infer) {
+// console.log("✅ Data tersimpan:", data);
+// toast.success("Data berhasil disimpan!");
// }
-// const successSubmit = (redirect: string) => {
-// MySwal.fire({
-// title: "Sukses",
-// text: "Data berhasil disimpan.",
-// icon: "success",
-// confirmButtonColor: "#3085d6",
-// confirmButtonText: "OK",
-// }).then(() => {
-// router.push(redirect);
-// });
-// };
-
-// function successTodo() {
-// let counter = 0;
-// for (const element of progressInfo) {
-// if (element.percentage == 100) {
-// counter++;
-// }
-// }
-// if (counter == progressInfo.length) {
-// setIsStartUpload(false);
-// // hideProgress();
-// Cookies.remove("idCreate");
-// successSubmit("/in/contributor/content/video");
-// }
-// }
-
-// const handleImageChange = (e: React.ChangeEvent) => {
-// const file = e.target.files?.[0];
-// if (file) {
-// setThumbnail(file); // Simpan file asli tanpa dimodifikasi
-// setPreview(URL.createObjectURL(file)); // Simpan preview string terpisah
-// console.log("Selected Thumbnail:", file);
-// }
-// };
-
-// const renderFilePreview = (file: FileWithPreview) => {
-// if (file.type.startsWith("image")) {
-// return (
-//
-// );
-// } else {
-// return ;
-// }
-// };
-
-// const handleRemoveFile = (file: FileWithPreview) => {
-// const uploadedFiles = files;
-// const filtered = uploadedFiles.filter((i) => i.name !== file.name);
-// setFiles([...filtered]);
-// };
-
-// const fileList = files.map((file) => (
-//
-//
-// {/*
{renderFilePreview(file)}
*/}
-//
-//
-//
{file.name}
-//
-// {Math.round(file.size / 100) / 10 > 1000 ? (
-// <>{(Math.round(file.size / 100) / 10000).toFixed(1)}>
-// ) : (
-// <>{(Math.round(file.size / 100) / 10).toFixed(1)}>
-// )}
-// {" kb"}
-//
-//
-//
-
-//
-//
-// ));
-
-// const handleRemoveAllFiles = () => {
-// setFiles([]);
-// };
-
-// useEffect(() => {
-// // Jika input title kosong, isi dengan hasil generate title
-// if (!getValues("title") && title) {
-// setValue("title", title);
-// }
-// }, [title, getValues, setValue]);
-
-// const handleRewriteClick = async () => {
-// setIsContentRewriteClicked(true);
-
-// const request = {
-// style: selectedWritingStyle,
-// lang: "id",
-// contextType: "text",
-// urlContext: null,
-// context: editorContent, // Ambil isi editor original
-// createdBy: roleId,
-// sentiment: "Humorous",
-// clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
-// };
-
-// const res = await generateDataRewrite(request);
-// close();
-
-// if (res?.error) {
-// console.error(res.message);
-// return false;
-// }
-
-// const newArticleId = res?.data?.data?.id;
-// setIsGeneratedArticle(true);
-
-// setArticleIds((prevIds: string[]) => {
-// if (prevIds.length < 3) {
-// return [...prevIds, newArticleId];
-// } else {
-// const updatedIds = [...prevIds];
-// updatedIds[2] = newArticleId;
-// return updatedIds;
-// }
-// });
-
-// Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds));
-// setShowRewriteEditor(true);
-// };
-
+// // --- RENDER ---
// return (
//