update
This commit is contained in:
parent
b8af83fe38
commit
2bcffbf0bb
|
|
@ -19,6 +19,7 @@ import GetSeoScore from "./get-seo-score-form";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import {
|
import {
|
||||||
|
createArticleSchedule,
|
||||||
deleteArticleFiles,
|
deleteArticleFiles,
|
||||||
getArticleByCategory,
|
getArticleByCategory,
|
||||||
getArticleById,
|
getArticleById,
|
||||||
|
|
@ -55,6 +56,8 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
|
import DatePicker from "react-datepicker";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
|
||||||
const ViewEditor = dynamic(
|
const ViewEditor = dynamic(
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -147,8 +150,14 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
||||||
const [approvalStatus, setApprovalStatus] = useState<number>(2);
|
const [approvalStatus, setApprovalStatus] = useState<number>(2);
|
||||||
const [approvalMessage, setApprovalMessage] = useState("");
|
const [approvalMessage, setApprovalMessage] = useState("");
|
||||||
const [detailData, setDetailData] = useState<any>();
|
const [detailData, setDetailData] = useState<any>();
|
||||||
const [startDateValue, setStartDateValue] = useState<any>(null);
|
// const [startDateValue, setStartDateValue] = useState<any>(null);
|
||||||
const [timeValue, setTimeValue] = useState("00:00");
|
// const [timeValue, setTimeValue] = useState("00:00");
|
||||||
|
const [status, setStatus] = useState<"publish" | "draft" | "scheduled">(
|
||||||
|
"publish"
|
||||||
|
);
|
||||||
|
const [isScheduled, setIsScheduled] = useState(false);
|
||||||
|
const [startDateValue, setStartDateValue] = useState<Date | undefined>();
|
||||||
|
const [startTimeValue, setStartTimeValue] = useState<string>("");
|
||||||
|
|
||||||
const { getRootProps, getInputProps } = useDropzone({
|
const { getRootProps, getInputProps } = useDropzone({
|
||||||
onDrop: (acceptedFiles) => {
|
onDrop: (acceptedFiles) => {
|
||||||
|
|
@ -193,7 +202,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
||||||
setValue("customCreatorName", data?.customCreatorName);
|
setValue("customCreatorName", data?.customCreatorName);
|
||||||
setValue("slug", data?.slug);
|
setValue("slug", data?.slug);
|
||||||
setValue("source", data?.source);
|
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(",") : []);
|
setValue("tags", data?.tags ? data.tags.split(",") : []);
|
||||||
setThumbnail(data?.thumbnailUrl);
|
setThumbnail(data?.thumbnailUrl);
|
||||||
setDiseId(data?.aiArticleId);
|
setDiseId(data?.aiArticleId);
|
||||||
|
|
@ -255,21 +270,28 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
||||||
|
|
||||||
const doPublish = async () => {
|
const doPublish = async () => {
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
title: "Publish Artikel?",
|
title: isScheduled ? "Jadwalkan Publikasi?" : "Publish Artikel Sekarang?",
|
||||||
text: "",
|
text: isScheduled
|
||||||
|
? "Artikel akan dipublish otomatis sesuai tanggal dan waktu yang kamu pilih."
|
||||||
|
: "",
|
||||||
icon: "warning",
|
icon: "warning",
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
cancelButtonColor: "#d33",
|
cancelButtonColor: "#d33",
|
||||||
confirmButtonColor: "#3085d6",
|
confirmButtonColor: "#3085d6",
|
||||||
confirmButtonText: "Submit",
|
confirmButtonText: isScheduled ? "Jadwalkan" : "Publish",
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
publish();
|
if (isScheduled) {
|
||||||
|
setStatus("scheduled");
|
||||||
|
publishScheduled();
|
||||||
|
} else {
|
||||||
|
publishNow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const publish = async () => {
|
const publishNow = async () => {
|
||||||
const response = await updateArticle(String(id), {
|
const response = await updateArticle(String(id), {
|
||||||
id: Number(id),
|
id: Number(id),
|
||||||
isPublish: true,
|
isPublish: true,
|
||||||
|
|
@ -286,8 +308,67 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
error(response.message);
|
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");
|
successSubmit("/admin/article");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -305,16 +386,16 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
||||||
// createdAt: `${startDateValue} ${timeValue}:00`,
|
// createdAt: `${startDateValue} ${timeValue}:00`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (startDateValue && timeValue) {
|
// if (startDateValue && timeValue) {
|
||||||
formData.createdAt = `${startDateValue} ${timeValue}:00`;
|
// formData.createdAt = `${startDateValue} ${timeValue}:00`;
|
||||||
}
|
// }
|
||||||
const response = await updateArticle(String(id), formData);
|
const response = await updateArticle(String(id), formData);
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
error(response.message);
|
error(response.message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const articleId = response?.data?.data?.id;
|
||||||
const formFiles = new FormData();
|
const formFiles = new FormData();
|
||||||
|
|
||||||
if (files?.length > 0) {
|
if (files?.length > 0) {
|
||||||
|
|
@ -331,6 +412,36 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
||||||
const resFile = await uploadArticleThumbnail(String(id), formFiles);
|
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();
|
close();
|
||||||
successSubmit("/admin/article");
|
successSubmit("/admin/article");
|
||||||
};
|
};
|
||||||
|
|
@ -934,7 +1045,63 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
||||||
{errors?.tags && (
|
{errors?.tags && (
|
||||||
<p className="text-red-400 text-sm mb-3">{errors.tags?.message}</p>
|
<p className="text-red-400 text-sm mb-3">{errors.tags?.message}</p>
|
||||||
)}
|
)}
|
||||||
{!isDetail && username === "admin-mabes" && (
|
<div className="flex flex-col gap-2 mt-3">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Switch
|
||||||
|
id="schedule-switch"
|
||||||
|
checked={isScheduled}
|
||||||
|
onCheckedChange={setIsScheduled}
|
||||||
|
/>
|
||||||
|
<label htmlFor="schedule-switch" className="text-black text-sm">
|
||||||
|
Publish dengan Jadwal
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isScheduled && (
|
||||||
|
<div className="flex flex-col lg:flex-row gap-3 mt-2">
|
||||||
|
{/* Pilih tanggal */}
|
||||||
|
<div className="w-full lg:w-[140px] flex flex-col gap-2">
|
||||||
|
<p className="text-sm">Tanggal</p>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
className="w-full !h-[37px] lg:h-[37px] border-1 rounded-lg text-black"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
{startDateValue
|
||||||
|
? startDateValue.toISOString().split("T")[0]
|
||||||
|
: "-"}
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="bg-transparent p-0">
|
||||||
|
<DatePicker
|
||||||
|
selected={startDateValue}
|
||||||
|
onChange={(date) =>
|
||||||
|
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"
|
||||||
|
/>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Pilih waktu */}
|
||||||
|
<div className="w-full lg:w-[140px] flex flex-col gap-2">
|
||||||
|
<p className="text-sm">Waktu</p>
|
||||||
|
<input
|
||||||
|
type="time"
|
||||||
|
value={startTimeValue}
|
||||||
|
onChange={(e) => setStartTimeValue(e.target.value)}
|
||||||
|
className="w-full border rounded-lg px-2 py-[6px] text-black"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{/* {!isDetail && username === "admin-mabes" && (
|
||||||
<>
|
<>
|
||||||
<p className="text-sm">Ubah Waktu Pembuatan</p>
|
<p className="text-sm">Ubah Waktu Pembuatan</p>
|
||||||
<div className="flex flex-row gap-2">
|
<div className="flex flex-row gap-2">
|
||||||
|
|
@ -966,7 +1133,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-row justify-end gap-3">
|
<div className="flex flex-row justify-end gap-3">
|
||||||
|
|
@ -1004,8 +1171,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{detailData?.isPublish === false && (
|
{detailData?.isPublish === false && (
|
||||||
<Button type="button" color="primary" onClick={doPublish}>
|
<Button
|
||||||
Publish
|
type="button"
|
||||||
|
color="primary"
|
||||||
|
onClick={doPublish}
|
||||||
|
disabled={isScheduled && !startDateValue}
|
||||||
|
>
|
||||||
|
{isScheduled ? "Jadwalkan" : "Publish"}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{/* {!isDetail && (
|
{/* {!isDetail && (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue