diff --git a/components/form/article/edit-article-form.tsx b/components/form/article/edit-article-form.tsx index 06b15bd..c3d7cf9 100644 --- a/components/form/article/edit-article-form.tsx +++ b/components/form/article/edit-article-form.tsx @@ -19,6 +19,7 @@ import GetSeoScore from "./get-seo-score-form"; import Link from "next/link"; import Cookies from "js-cookie"; import { + createArticleSchedule, deleteArticleFiles, getArticleByCategory, getArticleById, @@ -55,6 +56,8 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; +import DatePicker from "react-datepicker"; +import { Switch } from "@/components/ui/switch"; const ViewEditor = dynamic( () => { @@ -147,8 +150,14 @@ export default function EditArticleForm(props: { isDetail: boolean }) { const [approvalStatus, setApprovalStatus] = useState(2); const [approvalMessage, setApprovalMessage] = useState(""); const [detailData, setDetailData] = useState(); - const [startDateValue, setStartDateValue] = useState(null); - const [timeValue, setTimeValue] = useState("00:00"); + // const [startDateValue, setStartDateValue] = useState(null); + // const [timeValue, setTimeValue] = useState("00:00"); + const [status, setStatus] = useState<"publish" | "draft" | "scheduled">( + "publish" + ); + const [isScheduled, setIsScheduled] = useState(false); + const [startDateValue, setStartDateValue] = useState(); + const [startTimeValue, setStartTimeValue] = useState(""); const { getRootProps, getInputProps } = useDropzone({ onDrop: (acceptedFiles) => { @@ -193,7 +202,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) { setValue("customCreatorName", data?.customCreatorName); setValue("slug", data?.slug); setValue("source", data?.source); - setValue("description", data?.htmlDescription); + const cleanDescription = data?.htmlDescription + ? data.htmlDescription + .replace(/\\"/g, '"') + .replace(/\\n/g, "\n", "\\") + .trim() + : ""; + setValue("description", cleanDescription); setValue("tags", data?.tags ? data.tags.split(",") : []); setThumbnail(data?.thumbnailUrl); setDiseId(data?.aiArticleId); @@ -255,21 +270,28 @@ export default function EditArticleForm(props: { isDetail: boolean }) { const doPublish = async () => { MySwal.fire({ - title: "Publish Artikel?", - text: "", + title: isScheduled ? "Jadwalkan Publikasi?" : "Publish Artikel Sekarang?", + text: isScheduled + ? "Artikel akan dipublish otomatis sesuai tanggal dan waktu yang kamu pilih." + : "", icon: "warning", showCancelButton: true, cancelButtonColor: "#d33", confirmButtonColor: "#3085d6", - confirmButtonText: "Submit", + confirmButtonText: isScheduled ? "Jadwalkan" : "Publish", }).then((result) => { if (result.isConfirmed) { - publish(); + if (isScheduled) { + setStatus("scheduled"); + publishScheduled(); + } else { + publishNow(); + } } }); }; - const publish = async () => { + const publishNow = async () => { const response = await updateArticle(String(id), { id: Number(id), isPublish: true, @@ -286,8 +308,67 @@ export default function EditArticleForm(props: { isDetail: boolean }) { if (response?.error) { error(response.message); - return false; + return; } + + successSubmit("/admin/article"); + }; + + const publishScheduled = async () => { + if (!startDateValue) { + error("Tanggal belum dipilih!"); + return; + } + + const [hours, minutes] = startTimeValue + ? startTimeValue.split(":").map(Number) + : [0, 0]; + + const combinedDate = new Date(startDateValue); + combinedDate.setHours(hours, minutes, 0, 0); + + const formattedDateTime = `${combinedDate.getFullYear()}-${String( + combinedDate.getMonth() + 1 + ).padStart(2, "0")}-${String(combinedDate.getDate()).padStart( + 2, + "0" + )} ${String(combinedDate.getHours()).padStart(2, "0")}:${String( + combinedDate.getMinutes() + ).padStart(2, "0")}:00`; + + const response = await updateArticle(String(id), { + id: Number(id), + isPublish: false, + title: detailData?.title, + typeId: 1, + slug: detailData?.slug, + categoryIds: getValues("category") + .map((val) => val.id) + .join(","), + tags: getValues("tags").join(","), + description: htmlToString(getValues("description")), + htmlDescription: getValues("description"), + }); + + if (response?.error) { + error(response.message); + return; + } + + const articleId = response?.data?.data?.id ?? id; + const scheduleReq = { + id: articleId, + date: formattedDateTime, + }; + + console.log("📅 Mengirim jadwal publish:", scheduleReq); + const res = await createArticleSchedule(scheduleReq); + + if (res?.error) { + error("Gagal membuat jadwal publikasi."); + return; + } + successSubmit("/admin/article"); }; @@ -305,16 +386,16 @@ export default function EditArticleForm(props: { isDetail: boolean }) { // createdAt: `${startDateValue} ${timeValue}:00`, }; - if (startDateValue && timeValue) { - formData.createdAt = `${startDateValue} ${timeValue}:00`; - } + // if (startDateValue && timeValue) { + // formData.createdAt = `${startDateValue} ${timeValue}:00`; + // } const response = await updateArticle(String(id), formData); if (response?.error) { error(response.message); return false; } - + const articleId = response?.data?.data?.id; const formFiles = new FormData(); if (files?.length > 0) { @@ -331,6 +412,36 @@ export default function EditArticleForm(props: { isDetail: boolean }) { const resFile = await uploadArticleThumbnail(String(id), formFiles); } + if (status === "scheduled" && startDateValue) { + // ambil waktu, default 00:00 jika belum diisi + const [hours, minutes] = startTimeValue + ? startTimeValue.split(":").map(Number) + : [0, 0]; + + // gabungkan tanggal + waktu + const combinedDate = new Date(startDateValue); + combinedDate.setHours(hours, minutes, 0, 0); + + // format: 2025-10-08 14:30:00 + const formattedDateTime = `${combinedDate.getFullYear()}-${String( + combinedDate.getMonth() + 1 + ).padStart(2, "0")}-${String(combinedDate.getDate()).padStart( + 2, + "0" + )} ${String(combinedDate.getHours()).padStart(2, "0")}:${String( + combinedDate.getMinutes() + ).padStart(2, "0")}:00`; + + const request = { + id: articleId, + date: formattedDateTime, + }; + + console.log("📤 Sending schedule request:", request); + const res = await createArticleSchedule(request); + console.log("✅ Schedule response:", res); + } + close(); successSubmit("/admin/article"); }; @@ -934,7 +1045,63 @@ export default function EditArticleForm(props: { isDetail: boolean }) { {errors?.tags && (

{errors.tags?.message}

)} - {!isDetail && username === "admin-mabes" && ( +
+
+ + +
+ + {isScheduled && ( +
+ {/* Pilih tanggal */} +
+

Tanggal

+ + + + + + + setStartDateValue(date ?? undefined) + } + dateFormat="yyyy-MM-dd" + className="w-full border rounded-lg px-2 py-1 text-black cursor-pointer h-[150px]" + placeholderText="Pilih tanggal" + /> + + +
+ + {/* Pilih waktu */} +
+

Waktu

+ setStartTimeValue(e.target.value)} + className="w-full border rounded-lg px-2 py-[6px] text-black" + /> +
+
+ )} +
+ {/* {!isDetail && username === "admin-mabes" && ( <>

Ubah Waktu Pembuatan

@@ -966,7 +1133,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) { />
- )} + )} */}
@@ -1004,8 +1171,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) { )} {detailData?.isPublish === false && ( - )} {/* {!isDetail && (