"use client"; import React, { ChangeEvent, useEffect, useRef, useState } from "react"; import { useForm, Controller } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; import { useParams, useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import dynamic from "next/dynamic"; import Cookies from "js-cookie"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Separator } from "@/components/ui/separator"; import { ScrollArea } from "@/components/ui/scroll-area"; 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 { AlertCircle, FileText, Image, Loader2, Save, Trash2, Edit3, Globe, Users, Tag, Eye, Settings, CheckCircle, XCircle, } from "lucide-react"; import { Swiper, SwiperSlide } from "swiper/react"; import { Swiper as SwiperType } from "swiper"; import "swiper/css"; import "swiper/css/free-mode"; import "swiper/css/navigation"; import "swiper/css/pagination"; import "swiper/css/thumbs"; import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; import { convertSPIT, deleteSPIT, detailSPIT, getTagsBySubCategoryId, listEnableCategory, listEnableCategoryNew, } from "@/service/content/content"; import { generateDataRewrite, getDetailArticle } from "@/service/content/ai"; import { getCookiesDecrypt } from "@/lib/utils"; import { error } from "@/lib/swal"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; import { close, loading } from "@/config/swal"; interface Category { id: number; name: string; } interface Detail { id: string; contentTitle: string; contentDescription: string; slug: string; content: { id: number; name: string; }; contentCreator: string; creatorName: string; contentThumbnail: string; contentTag: string; categoryId?: number; contentList?: FileType[]; // keep as FileType[] } interface Option { id: string; label: string; } // Updated FileType to reflect API response interface FileType { contentId: number; contentFile: string; // URL contentType: "IMAGE" | "VIDEO" | string; contentFileRawType?: string; // e.g. video/mp4 or image/jpeg contentFileName?: string | null; thumbnailFileUrl?: string | null; fileName?: string | null; } interface PlacementData { mediaFileId: number; placements: string; } // Schema const formSchema = z.object({ contentTitle: z.string().min(1, { message: "Judul diperlukan" }), contentDescription: z.string().optional(), contentRewriteDescription: z.string().optional(), contentCreator: z.string().min(1, { message: "Creator diperlukan" }), }); type FormData = z.infer; // Constants const PUBLISH_OPTIONS: Option[] = [ { id: "all", label: "SEMUA" }, { id: "5", label: "UMUM" }, { id: "6", label: "JOURNALIS" }, { id: "7", label: "POLRI" }, { id: "8", label: "KSP" }, ]; const WRITING_STYLES = [ { value: "friendly", label: "Friendly" }, { value: "professional", label: "Profesional" }, { value: "informational", label: "Informational" }, { value: "neutral", label: "Neutral" }, { value: "witty", label: "Witty" }, ]; const PLACEMENT_OPTIONS = [ { value: "all", label: "Semua" }, { value: "mabes", label: "Nasional" }, { value: "polda", label: "Wilayah" }, { value: "international", label: "Internasional" }, ]; // Dynamic imports const CustomEditor = dynamic( () => import("@/components/editor/custom-editor"), { ssr: false, loading: () => (
Loading editor...
), } ); export default function FormConvertSPIT() { const MySwal = withReactContent(Swal); const router = useRouter(); const t = useTranslations("Form"); const { id } = useParams() as { id: string }; const [isAlreadySaved, setIsAlreadySaved] = useState(false); const { control, handleSubmit, setValue, formState: { errors, isSubmitting }, watch, } = useForm({ resolver: zodResolver(formSchema), defaultValues: { contentTitle: "", contentDescription: "", contentCreator: "", contentRewriteDescription: "", }, }); // Component state const [isLoading, setIsLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); const [isDeleting, setIsDeleting] = useState(false); const [detail, setDetail] = useState(null); const [categories, setCategories] = useState([]); const [selectedCategoryId, setSelectedCategoryId] = useState( null ); const [selectedFileType, setSelectedFileType] = useState< "original" | "rewrite" >("original"); const [selectedWritingStyle, setSelectedWritingStyle] = useState("professional"); const [showRewriteEditor, setShowRewriteEditor] = useState(false); const [isGeneratingRewrite, setIsGeneratingRewrite] = useState(false); const [isLoadingRewrite, setIsLoadingRewrite] = useState(false); // <-- changed: detailThumb is now FileType[] (objects from API) --> const [detailThumb, setDetailThumb] = useState([]); const [thumbsSwiper, setThumbsSwiper] = useState(null); const [files, setFiles] = useState([]); const [filePlacements, setFilePlacements] = useState([]); const [articleIds, setArticleIds] = useState([]); const [selectedArticleId, setSelectedArticleId] = useState( null ); const [articleBody, setArticleBody] = useState(""); const [tags, setTags] = useState([]); const [publishedFor, setPublishedFor] = useState([]); const [inputRef] = useState(useRef(null)); const userLevelId = getCookiesDecrypt("ulie"); const roleId = getCookiesDecrypt("urie"); const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); useEffect(() => { initializeComponent(); }, []); useEffect(() => { checkUserPermissions(); }, [userLevelId, roleId]); // Handle Swiper re-initialization when detailThumb changes useEffect(() => { if (thumbsSwiper && detailThumb.length > 0) { thumbsSwiper.update(); } }, [detailThumb, thumbsSwiper]); const initializeComponent = async () => { try { setIsLoading(true); await Promise.all([ loadCategories(), id ? loadDetail() : Promise.resolve(), ]); } catch (error) { console.error("Failed to initialize component:", error); MySwal.fire({ title: "Error", text: "Failed to load data. Please try again.", icon: "error", confirmButtonColor: "#3085d6", }); } finally { setIsLoading(false); } }; const checkUserPermissions = () => { if (userLevelId === "216" && roleId === "3") { setIsUserMabesApprover(true); } }; const loadCategories = async () => { try { const response = await listEnableCategoryNew("1", true); const categories = response?.data?.data?.content || []; setCategories(categories); const scheduleId = Cookies.get("scheduleId"); const scheduleType = Cookies.get("scheduleType"); if (scheduleId && scheduleType === "3") { const persRilisCategory = categories.find((cat: Category) => cat.name.toLowerCase().includes("pers rilis") ); if (persRilisCategory) { setSelectedCategoryId(persRilisCategory.id); await loadTags(persRilisCategory.id); } } } catch (error) { console.error("Failed to load categories:", error); } }; const loadTags = async (categoryId: number) => { try { const response = await getTagsBySubCategoryId(categoryId); if (response?.data?.data?.length > 0) { const apiTags = response?.data?.data?.map((tag: any) => tag.tagName); const tagsMerge = Array.from(new Set([...tags, ...apiTags])); setTags(tagsMerge); } } catch (error) { console.error("Failed to load tags:", error); } }; const loadDetail = async () => { loading(); try { const response = await detailSPIT(id); const details = response?.data?.data; setIsAlreadySaved(details?.isPublish ? true : false); if (!details) { throw new Error("Detail not found"); } setDetail(details); const contentList: FileType[] = (details.contentList || []).map( (it: any) => ({ contentId: it.contentId, contentFile: it.contentFile, contentType: it.contentType, contentFileRawType: it.contentFileRawType, contentFileName: it.contentFileName, thumbnailFileUrl: it.thumbnailFileUrl || null, fileName: it.contentFileName || null, }) ); setFiles(contentList); setDetailThumb(contentList); const fileCount = contentList.length || 0; setFilePlacements(Array(fileCount).fill([])); setValue("contentTitle", details.contentTitle || ""); setValue("contentDescription", details.contentDescription || ""); setValue("contentCreator", details.contentCreator || ""); setValue( "contentRewriteDescription", (details as any).contentRewriteDescription || "" ); if (details.categoryId) { setSelectedCategoryId(details.categoryId); await loadTags(details.categoryId); } if (details.contentTag) { const contentTags = details.contentTag .split(",") .map((tag: string) => tag.trim()); setTags((prev) => Array.from(new Set([...prev, ...contentTags]))); } } catch (error) { console.error("Failed to load detail:", error); throw error; } close(); }; const handleCategoryChange = async (categoryId: string) => { const id = Number(categoryId); setSelectedCategoryId(id); await loadTags(id); }; const handleRewriteClick = async () => { if (!detail?.contentDescription) { MySwal.fire({ title: "Warning", text: "Please add content description first", icon: "warning", confirmButtonColor: "#3085d6", }); return; } try { setIsGeneratingRewrite(true); const request = { style: selectedWritingStyle, lang: "id", contextType: "text", urlContext: null, context: detail.contentDescription, createdBy: roleId, sentiment: "Humorous", clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ", }; const response = await generateDataRewrite(request); console.log("REWRITE RESPONSE:", response); if (response?.error) { throw new Error(response.message); } const newArticleId = response?.data?.data?.id; setArticleIds((prev) => { const updated = [...prev]; if (updated.length < 3) { updated.push(newArticleId); } else { updated[2] = newArticleId; } return updated; }); setShowRewriteEditor(true); MySwal.fire({ title: "Success", text: "Content rewrite generated successfully", icon: "success", confirmButtonColor: "#3085d6", }); } catch (error) { console.error("Failed to generate rewrite:", error); MySwal.fire({ title: "Error", text: "Failed to generate content rewrite", icon: "error", confirmButtonColor: "#3085d6", }); } finally { setIsGeneratingRewrite(false); } }; const handleArticleSelect = async (articleId: string) => { try { setIsLoadingRewrite(true); setSelectedArticleId(articleId); let retryCount = 0; const maxRetries = 20; while (retryCount < maxRetries) { const response = await getDetailArticle(articleId); const articleData = response?.data?.data; if (articleData?.status === 2) { const cleanArticleBody = articleData.articleBody?.replace( /]*>/g, "" ); setArticleBody(cleanArticleBody || ""); setValue("contentRewriteDescription", cleanArticleBody || ""); break; } retryCount++; await new Promise((resolve) => setTimeout(resolve, 5000)); } if (retryCount >= maxRetries) { throw new Error("Timeout: Article processing took too long"); } } catch (error) { console.error("Failed to load article:", error); MySwal.fire({ title: "Error", text: "Failed to load article content", icon: "error", confirmButtonColor: "#3085d6", }); } finally { setIsLoadingRewrite(false); } }; const handleAddTag = (e: React.KeyboardEvent) => { if (e.key === "Enter" && inputRef.current?.value.trim()) { e.preventDefault(); const newTag = inputRef.current.value.trim(); if (!tags.includes(newTag)) { setTags((prev) => [...prev, newTag]); } inputRef.current.value = ""; } }; const handleRemoveTag = (index: number) => { setTags((prev) => prev.filter((_, i) => i !== index)); }; const handlePublishTargetChange = (optionId: string) => { if (optionId === "all") { setPublishedFor((prev) => prev.length === PUBLISH_OPTIONS.filter((opt) => opt.id !== "all").length ? [] : PUBLISH_OPTIONS.filter((opt) => opt.id !== "all").map( (opt) => opt.id ) ); } else { setPublishedFor((prev) => prev.includes(optionId) ? prev.filter((id) => id !== optionId && id !== "all") : [...prev.filter((id) => id !== "all"), optionId] ); } }; const handleFilePlacementChange = ( fileIndex: number, placement: string, checked: boolean ) => { setFilePlacements((prev) => { const updated = [...prev]; const currentPlacements = updated[fileIndex] || []; if (checked) { if (placement === "all") { updated[fileIndex] = ["all", "mabes", "polda", "international"]; } else { const newPlacements = [...currentPlacements, placement]; if (newPlacements.length === 3 && !newPlacements.includes("all")) { newPlacements.push("all"); } updated[fileIndex] = newPlacements; } } else { if (placement === "all") { updated[fileIndex] = []; } else { const newPlacements = currentPlacements.filter( (p) => p !== placement ); if (newPlacements.length === 3 && newPlacements.includes("all")) { updated[fileIndex] = newPlacements.filter((p) => p !== "all"); } else { updated[fileIndex] = newPlacements; } } } return updated; }); }; const handleSelectAllPlacements = (placement: string, checked: boolean) => { setFilePlacements((prev) => prev.map((filePlacements) => checked ? Array.from(new Set([...filePlacements, placement])) : filePlacements.filter((p) => p !== placement) ) ); }; const getPlacementData = (type: string) => { const placementData: PlacementData[] = []; if (type == "mabes") { for (let i = 0; i < filePlacements.length; i++) { if (filePlacements[i].length > 0) { const placements = filePlacements[i]; placementData.push({ mediaFileId: files[i].contentId, placements: placements.join(","), }); } } } else { for (let i = 0; i < files.length; i++) { placementData.push({ mediaFileId: files[i].contentId, placements: "polda", }); } } return placementData; }; const checkPlacement = (data: any) => { let temp = true; for (const element of data) { if (element.length < 1) { temp = false; break; } } return temp; }; const onSubmit = async (data: FormData) => { const pnmhTags = tags.filter((tag) => tag.toLowerCase().includes("pnmh")); if (pnmhTags.length > 1) { MySwal.fire({ title: "Error", text: "Tags penugasan hanya diperbolehkan 1 (satu) saja.", icon: "error", confirmButtonColor: "#3085d6", }); return false; } // if (!checkPlacement(filePlacements)) { // error("Select File Placement"); // return false; // } if (!selectedCategoryId) { error("Select a category"); return false; } if (publishedFor.length < 1) { error("Select Publish Target"); return false; } try { setIsSaving(true); const description = selectedFileType === "original" ? data.contentDescription : data.contentRewriteDescription; const requestData = { spitId: id, title: data.contentTitle, description, htmlDescription: description, tags: tags.join(", "), categoryId: selectedCategoryId, publishedFor: publishedFor.join(","), creator: data.contentCreator, files: isUserMabesApprover ? getPlacementData("mabes") : getPlacementData("polda"), }; await convertSPIT(requestData); MySwal.fire({ title: "Success", text: "Data saved successfully", icon: "success", confirmButtonColor: "#3085d6", }).then(() => { loadDetail(); }); } catch (error) { console.error("Failed to save:", error); MySwal.fire({ title: "Error", text: "Failed to save data", icon: "error", confirmButtonColor: "#3085d6", }); } finally { setIsSaving(false); } }; const handleDelete = async () => { const result = await MySwal.fire({ title: "Delete Content", text: "Are you sure you want to delete this content?", icon: "warning", showCancelButton: true, confirmButtonColor: "#dc3545", cancelButtonColor: "#6c757d", confirmButtonText: "Delete", cancelButtonText: "Cancel", }); if (result.isConfirmed) { try { setIsDeleting(true); await deleteSPIT(id); MySwal.fire({ title: "Success", text: "Content deleted successfully", icon: "success", confirmButtonColor: "#3085d6", }).then(() => { router.back(); }); } catch (error) { console.error("Failed to delete:", error); MySwal.fire({ title: "Error", text: "Failed to delete content", icon: "error", confirmButtonColor: "#3085d6", }); } finally { setIsDeleting(false); } } }; // Loading state if (isLoading) { return (

Loading form data...

); } return (
{/* Header */}

SPIT Convert Form

Convert and manage your SPIT content

{/* Main Content */}
{/* Basic Information */} Basic Information {/* Title */}
( )} /> {errors.contentTitle && ( {errors.contentTitle.message} )}
{/* Category */}
{/* Content Editor */} Content Editor {/* Pilih Upload Type */}
setSelectedFileType(value) } className="grid grid-cols-2 gap-4" >
{/* Tampilkan keduanya berdampingan */}
{/* Original Content */}
( )} />
{/* Rewrite Content */}
{showRewriteEditor && (
{articleIds.length > 0 && (
{articleIds.map((articleId, index) => ( ))}
)}
( )} />
)}
{/* Media Files */}
{detailThumb.length > 0 && ( Media Files
{detailThumb.map((item) => ( {item.contentType === "VIDEO" ? (
) : (
{`Media { console.error("Image load error:", e); e.currentTarget.style.display = "none"; }} />
)}
))}
{detailThumb.map((item) => ( {item.contentType === "VIDEO" ? (
{/* use preload metadata so browser doesn't download full video */}
) : (
{`Thumbnail { console.error( "Thumbnail image load error:", e ); e.currentTarget.style.display = "none"; }} />
)}
))}
)} {/* File Placement */} {files.length > 0 && isUserMabesApprover && ( File Placement {files.length > 1 && (
{PLACEMENT_OPTIONS.map((option) => (
handleSelectAllPlacements( option.value, Boolean(checked) ) } />
))}
)}
{files.map((file, index) => (
{file.contentType === "VIDEO" ? (
))}
)}
{/* Sidebar */}
Creator Information
( )} /> {errors.contentCreator && ( {errors.contentCreator.message} )}
{/* Preview */} {detail?.contentThumbnail && ( Preview Content thumbnail )} {/* Tags */} Tags
{tags.length > 0 && (
{tags.map((tag, index) => ( handleRemoveTag(index)} > {tag} ))}
)}
{/* Publish Targets */} Publish Targets {PUBLISH_OPTIONS.map((option) => (
opt.id !== "all" ).length : publishedFor.includes(option.id) } onCheckedChange={() => handlePublishTargetChange(option.id) } />
))}
{/* Submit Button */} {isAlreadySaved && ( Konten sudah disimpan. Anda tidak dapat menyimpan ulang. )}
); } // "use client"; // import React, { ChangeEvent, useEffect, useRef, useState } from "react"; // import { useForm, Controller } from "react-hook-form"; // import { zodResolver } from "@hookform/resolvers/zod"; // import * as z from "zod"; // import { useParams, useRouter } from "next/navigation"; // import { useTranslations } from "next-intl"; // import dynamic from "next/dynamic"; // import Cookies from "js-cookie"; // // UI Components // import { Input } from "@/components/ui/input"; // import { Button } from "@/components/ui/button"; // import { Label } from "@/components/ui/label"; // import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; // import { Badge } from "@/components/ui/badge"; // import { Alert, AlertDescription } from "@/components/ui/alert"; // import { Separator } from "@/components/ui/separator"; // import { ScrollArea } from "@/components/ui/scroll-area"; // import { // Select, // SelectContent, // SelectItem, // SelectTrigger, // SelectValue, // } from "@/components/ui/select"; // import { Checkbox } from "@/components/ui/checkbox"; // import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; // // Icons // import { // AlertCircle, // FileText, // Image, // Loader2, // Save, // Trash2, // Edit3, // Globe, // Users, // Tag, // Eye, // Settings, // CheckCircle, // XCircle, // } from "lucide-react"; // // Swiper // 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 { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; // // Services // import { // convertSPIT, // deleteSPIT, // detailSPIT, // getTagsBySubCategoryId, // listEnableCategory, // } from "@/service/content/content"; // import { generateDataRewrite, getDetailArticle } from "@/service/content/ai"; // // Utils // import { getCookiesDecrypt } from "@/lib/utils"; // import { error } from "@/lib/swal"; // import Swal from "sweetalert2"; // import withReactContent from "sweetalert2-react-content"; // import { close, loading } from "@/config/swal"; // // Types // interface Category { // id: number; // name: string; // } // interface Detail { // id: string; // contentTitle: string; // contentDescription: string; // slug: string; // content: { // id: number; // name: string; // }; // contentCreator: string; // creatorName: string; // contentThumbnail: string; // contentTag: string; // categoryId?: number; // contentList?: FileType[]; // } // interface Option { // id: string; // label: string; // } // interface FileType { // contentId: number; // contentFile: string; // thumbnailFileUrl: string; // fileName: string; // } // interface PlacementData { // mediaFileId: number; // placements: string; // } // // Schema // const formSchema = z.object({ // contentTitle: z.string().min(1, { message: "Judul diperlukan" }), // contentDescription: z.string().optional(), // contentRewriteDescription: z.string().optional(), // contentCreator: z.string().min(1, { message: "Creator diperlukan" }), // }); // type FormData = z.infer; // // Constants // const PUBLISH_OPTIONS: Option[] = [ // { id: "all", label: "SEMUA" }, // { id: "5", label: "UMUM" }, // { id: "6", label: "JOURNALIS" }, // { id: "7", label: "POLRI" }, // { id: "8", label: "KSP" }, // ]; // const WRITING_STYLES = [ // { value: "friendly", label: "Friendly" }, // { value: "professional", label: "Profesional" }, // { value: "informational", label: "Informational" }, // { value: "neutral", label: "Neutral" }, // { value: "witty", label: "Witty" }, // ]; // const PLACEMENT_OPTIONS = [ // { value: "all", label: "Semua" }, // { value: "mabes", label: "Nasional" }, // { value: "polda", label: "Wilayah" }, // { value: "international", label: "Internasional" }, // ]; // // Dynamic imports // const CustomEditor = dynamic( // () => import("@/components/editor/custom-editor"), // { // ssr: false, // loading: () => ( //
// // Loading editor... //
// ), // } // ); // export default function FormConvertSPIT() { // const MySwal = withReactContent(Swal); // const router = useRouter(); // const t = useTranslations("Form"); // const { id } = useParams() as { id: string }; // const [isAlreadySaved, setIsAlreadySaved] = useState(false); // // Form state // const { // control, // handleSubmit, // setValue, // formState: { errors, isSubmitting }, // watch, // } = useForm({ // resolver: zodResolver(formSchema), // defaultValues: { // contentTitle: "", // contentDescription: "", // contentCreator: "", // contentRewriteDescription: "", // }, // }); // // Component state // const [isLoading, setIsLoading] = useState(true); // const [isSaving, setIsSaving] = useState(false); // const [isDeleting, setIsDeleting] = useState(false); // const [detail, setDetail] = useState(null); // const [categories, setCategories] = useState([]); // const [selectedCategoryId, setSelectedCategoryId] = useState( // null // ); // const [selectedFileType, setSelectedFileType] = useState< // "original" | "rewrite" // >("original"); // const [selectedWritingStyle, setSelectedWritingStyle] = // useState("professional"); // const [showRewriteEditor, setShowRewriteEditor] = useState(false); // const [isGeneratingRewrite, setIsGeneratingRewrite] = useState(false); // const [isLoadingRewrite, setIsLoadingRewrite] = useState(false); // const [detailThumb, setDetailThumb] = useState([]); // const [thumbsSwiper, setThumbsSwiper] = useState(null); // const [files, setFiles] = useState([]); // const [filePlacements, setFilePlacements] = useState([]); // const [articleIds, setArticleIds] = useState([]); // const [selectedArticleId, setSelectedArticleId] = useState( // null // ); // const [articleBody, setArticleBody] = useState(""); // const [tags, setTags] = useState([]); // const [publishedFor, setPublishedFor] = useState([]); // const [inputRef] = useState(useRef(null)); // const userLevelId = getCookiesDecrypt("ulie"); // const roleId = getCookiesDecrypt("urie"); // const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); // useEffect(() => { // initializeComponent(); // }, []); // // useEffect(() => { // // const savedFlag = localStorage.getItem(`spit_saved_${id}`); // // if (savedFlag === "true") { // // setIsAlreadySaved(true); // // } // // }, [id]); // useEffect(() => { // checkUserPermissions(); // }, [userLevelId, roleId]); // const initializeComponent = async () => { // try { // setIsLoading(true); // await Promise.all([ // loadCategories(), // id ? loadDetail() : Promise.resolve(), // ]); // } catch (error) { // console.error("Failed to initialize component:", error); // MySwal.fire({ // title: "Error", // text: "Failed to load data. Please try again.", // icon: "error", // confirmButtonColor: "#3085d6", // }); // } finally { // setIsLoading(false); // } // }; // const checkUserPermissions = () => { // if (userLevelId === "216" && roleId === "3") { // setIsUserMabesApprover(true); // } // }; // const loadCategories = async () => { // try { // const response = await listEnableCategory("1"); // const categories = response?.data?.data?.content || []; // setCategories(categories); // // Auto-select "Pers Rilis" category if schedule type is 3 // const scheduleId = Cookies.get("scheduleId"); // const scheduleType = Cookies.get("scheduleType"); // if (scheduleId && scheduleType === "3") { // const persRilisCategory = categories.find((cat: Category) => // cat.name.toLowerCase().includes("pers rilis") // ); // if (persRilisCategory) { // setSelectedCategoryId(persRilisCategory.id); // await loadTags(persRilisCategory.id); // } // } // } catch (error) { // console.error("Failed to load categories:", error); // } // }; // const loadTags = async (categoryId: number) => { // try { // const response = await getTagsBySubCategoryId(categoryId); // if (response?.data?.data?.length > 0) { // const tagsMerge = [...tags, response?.data?.data]; // setTags(tagsMerge); // } // } catch (error) { // console.error("Failed to load tags:", error); // } // }; // const loadDetail = async () => { // loading(); // try { // const response = await detailSPIT(id); // const details = response?.data?.data; // setIsAlreadySaved(details?.isPublish ? true : false); // if (!details) { // throw new Error("Detail not found"); // } // setDetail(details); // setFiles(details.contentList || []); // setDetailThumb( // (details.contentList || []).map( // (file: FileType) => file.contentFile || "default-image.jpg" // ) // ); // // Initialize file placements // const fileCount = details.contentList?.length || 0; // setFilePlacements(Array(fileCount).fill([])); // // Set form values // setValue("contentTitle", details.contentTitle || ""); // setValue("contentDescription", details.contentDescription || ""); // setValue("contentCreator", details.contentCreator || ""); // setValue( // "contentRewriteDescription", // details.contentRewriteDescription || "" // ); // if (details.categoryId) { // setSelectedCategoryId(details.categoryId); // await loadTags(details.categoryId); // } // if (details.contentTag) { // const initialTags = details.contentTag // .split(",") // .map((tag: string) => tag.trim()); // setTags(initialTags); // } // } catch (error) { // console.error("Failed to load detail:", error); // throw error; // } // close(); // }; // const handleCategoryChange = async (categoryId: string) => { // const id = Number(categoryId); // setSelectedCategoryId(id); // await loadTags(id); // }; // const handleRewriteClick = async () => { // if (!detail?.contentDescription) { // MySwal.fire({ // title: "Warning", // text: "Please add content description first", // icon: "warning", // confirmButtonColor: "#3085d6", // }); // return; // } // try { // setIsGeneratingRewrite(true); // const request = { // style: selectedWritingStyle, // lang: "id", // contextType: "text", // urlContext: null, // context: detail.contentDescription, // createdBy: roleId, // sentiment: "Humorous", // clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ", // }; // const response = await generateDataRewrite(request); // if (response?.error) { // throw new Error(response.message); // } // const newArticleId = response?.data?.data?.id; // setArticleIds((prev) => { // const updated = [...prev]; // if (updated.length < 3) { // updated.push(newArticleId); // } else { // updated[2] = newArticleId; // } // return updated; // }); // setShowRewriteEditor(true); // MySwal.fire({ // title: "Success", // text: "Content rewrite generated successfully", // icon: "success", // confirmButtonColor: "#3085d6", // }); // } catch (error) { // console.error("Failed to generate rewrite:", error); // MySwal.fire({ // title: "Error", // text: "Failed to generate content rewrite", // icon: "error", // confirmButtonColor: "#3085d6", // }); // } finally { // setIsGeneratingRewrite(false); // } // }; // const handleArticleSelect = async (articleId: string) => { // try { // setIsLoadingRewrite(true); // setSelectedArticleId(articleId); // let retryCount = 0; // const maxRetries = 20; // while (retryCount < maxRetries) { // const response = await getDetailArticle(articleId); // const articleData = response?.data?.data; // if (articleData?.status === 2) { // const cleanArticleBody = articleData.articleBody?.replace( // /]*>/g, // "" // ); // setArticleBody(cleanArticleBody || ""); // setValue("contentRewriteDescription", cleanArticleBody || ""); // break; // } // retryCount++; // await new Promise((resolve) => setTimeout(resolve, 5000)); // } // if (retryCount >= maxRetries) { // throw new Error("Timeout: Article processing took too long"); // } // } catch (error) { // console.error("Failed to load article:", error); // MySwal.fire({ // title: "Error", // text: "Failed to load article content", // icon: "error", // confirmButtonColor: "#3085d6", // }); // } finally { // setIsLoadingRewrite(false); // } // }; // const handleAddTag = (e: React.KeyboardEvent) => { // if (e.key === "Enter" && inputRef.current?.value.trim()) { // e.preventDefault(); // const newTag = inputRef.current.value.trim(); // if (!tags.includes(newTag)) { // setTags((prev) => [...prev, newTag]); // } // inputRef.current.value = ""; // } // }; // const handleRemoveTag = (index: number) => { // setTags((prev) => prev.filter((_, i) => i !== index)); // }; // const handlePublishTargetChange = (optionId: string) => { // if (optionId === "all") { // setPublishedFor((prev) => // prev.length === PUBLISH_OPTIONS.filter((opt) => opt.id !== "all").length // ? [] // : PUBLISH_OPTIONS.filter((opt) => opt.id !== "all").map( // (opt) => opt.id // ) // ); // } else { // setPublishedFor((prev) => // prev.includes(optionId) // ? prev.filter((id) => id !== optionId && id !== "all") // : [...prev.filter((id) => id !== "all"), optionId] // ); // } // }; // const handleFilePlacementChange = ( // fileIndex: number, // placement: string, // checked: boolean // ) => { // setFilePlacements((prev) => { // const updated = [...prev]; // const currentPlacements = updated[fileIndex] || []; // if (checked) { // if (placement === "all") { // updated[fileIndex] = ["all", "mabes", "polda", "international"]; // } else { // const newPlacements = [...currentPlacements, placement]; // if (newPlacements.length === 3 && !newPlacements.includes("all")) { // newPlacements.push("all"); // } // updated[fileIndex] = newPlacements; // } // } else { // if (placement === "all") { // updated[fileIndex] = []; // } else { // const newPlacements = currentPlacements.filter( // (p) => p !== placement // ); // if (newPlacements.length === 3 && newPlacements.includes("all")) { // updated[fileIndex] = newPlacements.filter((p) => p !== "all"); // } else { // updated[fileIndex] = newPlacements; // } // } // } // return updated; // }); // }; // const handleSelectAllPlacements = (placement: string, checked: boolean) => { // setFilePlacements((prev) => // prev.map((filePlacements) => // checked // ? Array.from(new Set([...filePlacements, placement])) // : filePlacements.filter((p) => p !== placement) // ) // ); // }; // const getPlacementData = () => { // const placementData = []; // console.log("filePlacements : ", filePlacements); // for (let i = 0; i < filePlacements.length; i++) { // if (filePlacements[i].length > 0) { // const placements = filePlacements[i]; // placementData.push({ // mediaFileId: files[i].contentId, // placements: placements.join(","), // }); // } // } // return placementData; // }; // const checkPlacement = (data: any) => { // let temp = true; // for (const element of data) { // if (element.length < 1) { // temp = false; // break; // } // } // return temp; // }; // // Form submission // const onSubmit = async (data: FormData) => { // const pnmhTags = tags.filter((tag) => tag.toLowerCase().includes("pnmh")); // if (pnmhTags.length > 1) { // MySwal.fire({ // title: "Error", // text: "Tags penugasan hanya diperbolehkan 1 (satu) saja.", // icon: "error", // confirmButtonColor: "#3085d6", // }); // return false; // } // if (!checkPlacement(filePlacements)) { // error("Select File Placement"); // return false; // } // if (!selectedCategoryId) { // error("Select a category"); // return false; // } // if (publishedFor.length < 1) { // error("Select Publish Target"); // return false; // } // try { // setIsSaving(true); // const description = // selectedFileType === "original" // ? data.contentDescription // : data.contentRewriteDescription; // const requestData = { // spitId: id, // title: data.contentTitle, // description, // htmlDescription: description, // tags: tags.join(", "), // categoryId: selectedCategoryId, // publishedFor: publishedFor.join(","), // creator: data.contentCreator, // files: isUserMabesApprover ? getPlacementData() : [], // }; // await convertSPIT(requestData); // // localStorage.setItem(`spit_saved_${id}`, "true"); // // setIsAlreadySaved(true); // MySwal.fire({ // title: "Success", // text: "Data saved successfully", // icon: "success", // confirmButtonColor: "#3085d6", // }).then(() => { // // router.push("/in/contributor/content/spit"); // // router.replace(`${window.location.pathname}?id=${id}`); // loadDetail(); // }); // } catch (error) { // console.error("Failed to save:", error); // MySwal.fire({ // title: "Error", // text: "Failed to save data", // icon: "error", // confirmButtonColor: "#3085d6", // }); // } finally { // setIsSaving(false); // } // }; // const handleDelete = async () => { // const result = await MySwal.fire({ // title: "Delete Content", // text: "Are you sure you want to delete this content?", // icon: "warning", // showCancelButton: true, // confirmButtonColor: "#dc3545", // cancelButtonColor: "#6c757d", // confirmButtonText: "Delete", // cancelButtonText: "Cancel", // }); // if (result.isConfirmed) { // try { // setIsDeleting(true); // await deleteSPIT(id); // MySwal.fire({ // title: "Success", // text: "Content deleted successfully", // icon: "success", // confirmButtonColor: "#3085d6", // }).then(() => { // router.back(); // }); // } catch (error) { // console.error("Failed to delete:", error); // MySwal.fire({ // title: "Error", // text: "Failed to delete content", // icon: "error", // confirmButtonColor: "#3085d6", // }); // } finally { // setIsDeleting(false); // } // } // }; // // Loading state // if (isLoading) { // return ( //
//
// //

Loading form data...

//
//
// ); // } // return ( //
// {/* Header */} //
//
//

// SPIT Convert Form //

//

// Convert and manage your SPIT content //

//
//
// // //
//
//
//
// {/* Main Content */} //
// {/* Basic Information */} // // // // // Basic Information // // // // {/* Title */} //
// // ( // // )} // /> // {errors.contentTitle && ( // // // // {errors.contentTitle.message} // // // )} //
// {/* Category */} //
// // //
//
//
// {/* Content Editor */} // // // // // Content Editor // // // // // setSelectedFileType(value) // } // className="grid grid-cols-2 gap-4" // > //
// // //
//
// // //
//
// {/* Original Content */} // {selectedFileType === "original" && ( //
// // ( // // )} // /> //
// )} // {/* Content Rewrite */} // {selectedFileType === "rewrite" && ( //
//
//
// // //
// //
// {showRewriteEditor && ( //
// {articleIds.length > 0 && ( //
// {articleIds.map((articleId, index) => ( // // ))} //
// )} //
// // ( // // )} // /> //
//
// )} //
// )} //
//
// {/* Media Files */} // {detailThumb.length > 0 && ( // // // // // Media Files // // // //
// // {detailThumb.map((image, index) => ( // // {`Media // // ))} // // // {detailThumb.map((image, index) => ( // // {`Thumbnail // // ))} // //
//
//
// )} // {/* File Placement */} // {files.length > 0 && isUserMabesApprover && ( // // // // // File Placement // // // // {files.length > 1 && ( //
// {PLACEMENT_OPTIONS.map((option) => ( //
// // handleSelectAllPlacements( // option.value, // Boolean(checked) // ) // } // /> // //
// ))} //
// )} //
// {files.map((file, index) => ( //
// {file.fileName} //
//

{file.fileName}

//
// {PLACEMENT_OPTIONS.map((option) => ( //
// // handleFilePlacementChange( // index, // option.value, // Boolean(checked) // ) // } // /> // //
// ))} //
//
//
// ))} //
//
//
// )} //
// {/* Sidebar */} //
// {/* Creator Information */} // // // // // Creator Information // // // //
// // ( // // )} // /> // {errors.contentCreator && ( // // // // {errors.contentCreator.message} // // // )} //
//
//
// {/* Preview */} // {detail?.contentThumbnail && ( // // // // // Preview // // // // Content thumbnail // // // )} // {/* Tags */} // // // // // Tags // // // //
// // //
// {tags.length > 0 && ( //
// {tags.map((tag, index) => ( // handleRemoveTag(index)} // > // {tag} // // // ))} //
// )} //
//
// {/* Publish Targets */} // // // // // Publish Targets // // // // {PUBLISH_OPTIONS.map((option) => ( //
// opt.id !== "all") // .length // : publishedFor.includes(option.id) // } // onCheckedChange={() => // handlePublishTargetChange(option.id) // } // /> // //
// ))} //
//
// {/* Submit Button */} // // // // {isAlreadySaved && ( // // // // Konten sudah disimpan. Anda tidak dapat menyimpan ulang. // // // )} // // //
//
//
//
// ); // }