diff --git a/components/form/content/spit-convert-form.tsx b/components/form/content/spit-convert-form.tsx index fdaee85d..8d7f85e5 100644 --- a/components/form/content/spit-convert-form.tsx +++ b/components/form/content/spit-convert-form.tsx @@ -28,13 +28,13 @@ import { Checkbox } from "@/components/ui/checkbox"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; // Icons -import { - AlertCircle, - FileText, - Image, - Loader2, - Save, - Trash2, +import { + AlertCircle, + FileText, + Image, + Loader2, + Save, + Trash2, Edit3, Globe, Users, @@ -42,7 +42,7 @@ import { Eye, Settings, CheckCircle, - XCircle + XCircle, } from "lucide-react"; // Swiper @@ -62,10 +62,7 @@ import { getTagsBySubCategoryId, listEnableCategory, } from "@/service/content/content"; -import { - generateDataRewrite, - getDetailArticle, -} from "@/service/content/ai"; +import { generateDataRewrite, getDetailArticle } from "@/service/content/ai"; // Utils import { getCookiesDecrypt } from "@/lib/utils"; @@ -150,14 +147,14 @@ const PLACEMENT_OPTIONS = [ // Dynamic imports const CustomEditor = dynamic( () => import("@/components/editor/custom-editor"), - { + { ssr: false, loading: () => (
Loading editor...
- ) + ), } ); @@ -190,24 +187,31 @@ export default function FormConvertSPIT() { 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 [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); - + // Media state const [detailThumb, setDetailThumb] = useState([]); const [thumbsSwiper, setThumbsSwiper] = useState(null); const [files, setFiles] = useState([]); const [filePlacements, setFilePlacements] = useState([]); - + // Content rewrite state const [articleIds, setArticleIds] = useState([]); - const [selectedArticleId, setSelectedArticleId] = useState(null); + const [selectedArticleId, setSelectedArticleId] = useState( + null + ); const [articleBody, setArticleBody] = useState(""); - + // Form data state const [tags, setTags] = useState([]); const [publishedFor, setPublishedFor] = useState([]); @@ -262,7 +266,7 @@ export default function FormConvertSPIT() { // 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") @@ -281,7 +285,7 @@ export default function FormConvertSPIT() { try { const response = await getTagsBySubCategoryId(categoryId); if (response?.data?.data?.length > 0) { - const tagsMerge = [...tags, response?.data?.data] + const tagsMerge = [...tags, response?.data?.data]; setTags(tagsMerge); } } catch (error) { @@ -293,7 +297,7 @@ export default function FormConvertSPIT() { try { const response = await detailSPIT(id); const details = response?.data?.data; - + if (!details) { throw new Error("Detail not found"); } @@ -301,11 +305,11 @@ export default function FormConvertSPIT() { setDetail(details); setFiles(details.contentList || []); setDetailThumb( - (details.contentList || []).map((file: FileType) => - file.contentFile || "default-image.jpg" + (details.contentList || []).map( + (file: FileType) => file.contentFile || "default-image.jpg" ) ); - + // Initialize file placements const fileCount = details.contentList?.length || 0; setFilePlacements(Array(fileCount).fill([])); @@ -314,7 +318,10 @@ export default function FormConvertSPIT() { setValue("contentTitle", details.contentTitle || ""); setValue("contentDescription", details.contentDescription || ""); setValue("contentCreator", details.contentCreator || ""); - setValue("contentRewriteDescription", details.contentRewriteDescription || ""); + setValue( + "contentRewriteDescription", + details.contentRewriteDescription || "" + ); // Set category if (details.categoryId) { @@ -324,7 +331,9 @@ export default function FormConvertSPIT() { // Set tags if (details.contentTag) { - const initialTags = details.contentTag.split(",").map((tag: string) => tag.trim()); + const initialTags = details.contentTag + .split(",") + .map((tag: string) => tag.trim()); setTags(initialTags); } } catch (error) { @@ -365,13 +374,13 @@ export default function FormConvertSPIT() { }; const response = await generateDataRewrite(request); - + if (response?.error) { throw new Error(response.message); } const newArticleId = response?.data?.data?.id; - setArticleIds(prev => { + setArticleIds((prev) => { const updated = [...prev]; if (updated.length < 3) { updated.push(newArticleId); @@ -405,23 +414,26 @@ export default function FormConvertSPIT() { 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, ""); + const cleanArticleBody = articleData.articleBody?.replace( + /]*>/g, + "" + ); setArticleBody(cleanArticleBody || ""); setValue("contentRewriteDescription", cleanArticleBody || ""); break; } retryCount++; - await new Promise(resolve => setTimeout(resolve, 5000)); + await new Promise((resolve) => setTimeout(resolve, 5000)); } if (retryCount >= maxRetries) { @@ -444,40 +456,46 @@ export default function FormConvertSPIT() { if (e.key === "Enter" && inputRef.current?.value.trim()) { e.preventDefault(); const newTag = inputRef.current.value.trim(); - + if (!tags.includes(newTag)) { - setTags(prev => [...prev, newTag]); + setTags((prev) => [...prev, newTag]); } - + inputRef.current.value = ""; } }; const handleRemoveTag = (index: number) => { - setTags(prev => prev.filter((_, i) => i !== index)); + 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) + 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] + 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 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"]; @@ -492,25 +510,27 @@ export default function FormConvertSPIT() { if (placement === "all") { updated[fileIndex] = []; } else { - const newPlacements = currentPlacements.filter(p => p !== placement); + const newPlacements = currentPlacements.filter( + (p) => p !== placement + ); if (newPlacements.length === 3 && newPlacements.includes("all")) { - updated[fileIndex] = newPlacements.filter(p => p !== "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 + setFilePlacements((prev) => + prev.map((filePlacements) => + checked ? Array.from(new Set([...filePlacements, placement])) - : filePlacements.filter(p => p !== placement) + : filePlacements.filter((p) => p !== placement) ) ); }; @@ -520,7 +540,7 @@ export default function FormConvertSPIT() { console.log("filePlacements : ", filePlacements); for (let i = 0; i < filePlacements.length; i++) { if (filePlacements[i].length > 0) { - const placements = filePlacements[i]; + const placements = filePlacements[i]; placementData.push({ mediaFileId: files[i].contentId, placements: placements.join(","), @@ -530,15 +550,38 @@ export default function FormConvertSPIT() { 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) => { + if (!checkPlacement(filePlacements)) { + error("Select File Placement"); + return false; + } + + if (publishedFor.length < 1) { + error("Select Publish Target"); + return false; + } + try { setIsSaving(true); - - const description = selectedFileType === "original" - ? data.contentDescription - : data.contentRewriteDescription; - + + const description = + selectedFileType === "original" + ? data.contentDescription + : data.contentRewriteDescription; + const requestData = { spitId: id, title: data.contentTitle, @@ -552,7 +595,7 @@ export default function FormConvertSPIT() { }; await convertSPIT(requestData); - + MySwal.fire({ title: "Success", text: "Data saved successfully", @@ -590,7 +633,7 @@ export default function FormConvertSPIT() { try { setIsDeleting(true); await deleteSPIT(id); - + MySwal.fire({ title: "Success", text: "Content deleted successfully", @@ -630,17 +673,15 @@ export default function FormConvertSPIT() { {/* Header */}
-

SPIT Convert Form

+

+ SPIT Convert Form +

Convert and manage your SPIT content

- @@ -734,7 +775,9 @@ export default function FormConvertSPIT() { setSelectedFileType(value)} + onValueChange={(value: "original" | "rewrite") => + setSelectedFileType(value) + } className="grid grid-cols-2 gap-4" >
@@ -789,7 +832,9 @@ export default function FormConvertSPIT() { ))} @@ -870,7 +920,7 @@ export default function FormConvertSPIT() { ))} - + 1 && (
{PLACEMENT_OPTIONS.map((option) => ( -
+
- handleSelectAllPlacements(option.value, Boolean(checked)) + handleSelectAllPlacements( + option.value, + Boolean(checked) + ) } /> -
@@ -936,12 +995,21 @@ export default function FormConvertSPIT() {

{file.fileName}

{PLACEMENT_OPTIONS.map((option) => ( -
+
- handleFilePlacementChange(index, option.value, Boolean(checked)) + handleFilePlacementChange( + index, + option.value, + Boolean(checked) + ) } />