2025-01-07 11:52:16 +00:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import HeaderManagement from "@/components/landing-page/header-management";
|
|
|
|
|
import SidebarManagement from "@/components/landing-page/sidebar-management";
|
|
|
|
|
import { useRouter } from "@/i18n/routing";
|
2025-01-07 19:36:40 +00:00
|
|
|
import { getCookiesDecrypt, setCookiesEncrypt } from "@/lib/utils";
|
2025-01-08 06:15:04 +00:00
|
|
|
import { useParams, useSearchParams } from "next/navigation";
|
2025-01-07 19:36:40 +00:00
|
|
|
import React, { useEffect, useState } from "react";
|
2025-01-07 11:52:16 +00:00
|
|
|
import Swal from "sweetalert2";
|
|
|
|
|
import withReactContent from "sweetalert2-react-content";
|
2025-06-03 05:46:06 +00:00
|
|
|
import {
|
|
|
|
|
Select,
|
|
|
|
|
SelectContent,
|
|
|
|
|
SelectGroup,
|
|
|
|
|
SelectItem,
|
|
|
|
|
SelectLabel,
|
|
|
|
|
SelectTrigger,
|
|
|
|
|
SelectValue,
|
|
|
|
|
} from "@/components/ui/select";
|
2025-01-07 19:36:40 +00:00
|
|
|
import { Controller, useForm } from "react-hook-form";
|
|
|
|
|
import * as z from "zod";
|
|
|
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
2025-06-03 05:46:06 +00:00
|
|
|
import {
|
|
|
|
|
generateDataArticle,
|
|
|
|
|
generateDataRewrite,
|
|
|
|
|
getDetailArticle,
|
|
|
|
|
} from "@/service/content/ai";
|
2025-01-07 19:36:40 +00:00
|
|
|
import { Button } from "@/components/ui/button";
|
2025-01-08 06:15:04 +00:00
|
|
|
import { close, error, loading } from "@/config/swal";
|
2025-01-07 19:36:40 +00:00
|
|
|
import { saveContentRewrite } from "@/service/content/content";
|
|
|
|
|
import { getPublicSuggestionList } from "@/service/landing/landing";
|
|
|
|
|
import { getDetail } from "@/service/detail/detail";
|
|
|
|
|
import { yupResolver } from "@hookform/resolvers/yup";
|
|
|
|
|
import * as Yup from "yup";
|
|
|
|
|
import Cookies from "js-cookie";
|
2025-01-08 06:15:04 +00:00
|
|
|
import { Input } from "@/components/ui/input";
|
|
|
|
|
import { Textarea } from "@/components/ui/textarea";
|
2025-02-15 14:43:19 +00:00
|
|
|
import { useTranslations } from "next-intl";
|
2025-06-07 13:28:41 +00:00
|
|
|
import dynamic from "next/dynamic";
|
2025-01-07 11:52:16 +00:00
|
|
|
|
2025-01-07 19:36:40 +00:00
|
|
|
const imageSchema = z.object({
|
|
|
|
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
2025-01-08 06:15:04 +00:00
|
|
|
mainKeyword: z.string().min(1, { message: "Keyword diperlukan" }),
|
2025-06-03 05:46:06 +00:00
|
|
|
seo: z.string().min(1, {
|
|
|
|
|
message:
|
|
|
|
|
"Tuliskan kata kunci atau frasa yang relevan dengan blog Anda, lalu tekan enter",
|
|
|
|
|
}),
|
|
|
|
|
description: z
|
|
|
|
|
.string()
|
|
|
|
|
.min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }),
|
2025-01-07 19:36:40 +00:00
|
|
|
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
|
|
|
|
// tags: z.string().min(1, { message: "Judul diperlukan" }),
|
|
|
|
|
});
|
2025-06-07 13:28:41 +00:00
|
|
|
const CustomEditor = dynamic(
|
|
|
|
|
() => {
|
|
|
|
|
return import("@/components/editor/custom-editor");
|
|
|
|
|
},
|
|
|
|
|
{ ssr: false }
|
|
|
|
|
);
|
2025-01-07 19:36:40 +00:00
|
|
|
|
2025-01-12 08:21:11 +00:00
|
|
|
const page = (props: any) => {
|
2025-01-07 19:36:40 +00:00
|
|
|
const { states } = props;
|
2025-01-07 11:52:16 +00:00
|
|
|
const MySwal = withReactContent(Swal);
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const [, setLoadingState] = useState(false);
|
|
|
|
|
const searchParams = useSearchParams();
|
2025-01-08 06:15:04 +00:00
|
|
|
const getParams = useParams();
|
|
|
|
|
const id: any = getParams?.id;
|
2025-01-07 19:36:40 +00:00
|
|
|
const [content, setContent] = useState<any>([]);
|
2025-01-07 11:52:16 +00:00
|
|
|
const [isFromSPIT, setIsFromSPIT] = useState(false);
|
|
|
|
|
const [listSuggestion, setListSuggestion] = useState();
|
2025-01-07 19:36:40 +00:00
|
|
|
const [main, setMain] = useState<any>();
|
2025-01-07 11:52:16 +00:00
|
|
|
const userId = getCookiesDecrypt("uie");
|
|
|
|
|
const userRoleId = getCookiesDecrypt("urie");
|
2025-01-07 19:36:40 +00:00
|
|
|
const [articleIds, setArticleIds] = useState<any>([]);
|
2025-01-07 11:52:16 +00:00
|
|
|
const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
|
2025-01-07 19:36:40 +00:00
|
|
|
const [selectedArticleId, setSelectedArticleId] = useState<any>(null);
|
2025-01-07 11:52:16 +00:00
|
|
|
const [articleBody, setArticleBody] = useState("");
|
|
|
|
|
const [selectedAdvConfig, setSelectedAdvConfig] = useState("");
|
2025-06-09 09:50:30 +00:00
|
|
|
const [selectedWritingStyle, setSelectedWritingStyle] =
|
|
|
|
|
useState("profesional");
|
|
|
|
|
const [selectedContextType, setSelectedContextType] = useState("article");
|
|
|
|
|
const [selectedLanguage, setSelectedLanguage] = useState("id");
|
2025-01-07 11:52:16 +00:00
|
|
|
const [selectedTitle, setSelectedTitle] = useState("");
|
2025-06-09 09:50:30 +00:00
|
|
|
const [selectedSize, setSelectedSize] = useState("news");
|
2025-01-07 19:36:40 +00:00
|
|
|
const [detailArticle, setDetailArticle] = useState<any>(null);
|
|
|
|
|
const [isLoadingData, setIsLoadingData] = useState<boolean>(false);
|
|
|
|
|
const [detailData, setDetailData] = useState<any>(null);
|
|
|
|
|
const [articleImages, setArticleImages] = useState<string[]>([]);
|
2025-02-15 14:43:19 +00:00
|
|
|
const t = useTranslations("LandingPage");
|
2025-01-07 11:52:16 +00:00
|
|
|
|
|
|
|
|
const userLevelId = getCookiesDecrypt("ulie");
|
|
|
|
|
const roleId = getCookiesDecrypt("urie");
|
2025-01-08 06:15:04 +00:00
|
|
|
|
2025-01-07 19:36:40 +00:00
|
|
|
type ImageSchema = z.infer<typeof imageSchema>;
|
|
|
|
|
|
|
|
|
|
const validationSchema = Yup.object().shape({
|
|
|
|
|
title: Yup.string().required("Judul tidak boleh kosong"),
|
2025-01-08 06:15:04 +00:00
|
|
|
mainKeyword: Yup.string().required("Keyword tidak boleh kosong"),
|
2025-06-03 05:46:06 +00:00
|
|
|
description: Yup.string().required(
|
|
|
|
|
"Narasi Penugasan harus lebih dari 2 karakter."
|
|
|
|
|
),
|
2025-01-07 19:36:40 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let componentMounted = true;
|
|
|
|
|
|
|
|
|
|
const { control } = useForm<ImageSchema>({
|
|
|
|
|
resolver: zodResolver(imageSchema),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const formOptions = {
|
|
|
|
|
resolver: yupResolver(validationSchema),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const {
|
|
|
|
|
register,
|
|
|
|
|
handleSubmit,
|
|
|
|
|
reset,
|
|
|
|
|
formState: { errors },
|
|
|
|
|
setValue,
|
2025-01-08 06:15:04 +00:00
|
|
|
getValues,
|
2025-01-07 19:36:40 +00:00
|
|
|
} = useForm(formOptions);
|
|
|
|
|
|
|
|
|
|
const save = async (data: any) => {
|
|
|
|
|
const request = {
|
|
|
|
|
title: data.title,
|
|
|
|
|
articleId: detailArticle?.id,
|
|
|
|
|
mediaUploadId: id.split("-")?.[0],
|
|
|
|
|
articleBody: detailArticle?.articleBody,
|
|
|
|
|
metaTitle: detailArticle?.metaTitle,
|
|
|
|
|
metaDescription: detailArticle?.metaDescription,
|
|
|
|
|
mainKeyword: detailArticle?.mainKeyword,
|
|
|
|
|
additionalKeyword: detailArticle?.additionalKeyword,
|
|
|
|
|
articleSize: detailArticle?.articleSize,
|
|
|
|
|
style: detailArticle?.style,
|
|
|
|
|
website: detailArticle?.website,
|
|
|
|
|
imageUrl: detailArticle?.imageUrl,
|
|
|
|
|
};
|
|
|
|
|
loading();
|
|
|
|
|
const res = await saveContentRewrite(request);
|
|
|
|
|
if (res?.error) {
|
|
|
|
|
error(res?.message);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
successSubmit();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function successSubmit() {
|
|
|
|
|
MySwal.fire({
|
|
|
|
|
title: "Sukses",
|
|
|
|
|
icon: "success",
|
|
|
|
|
confirmButtonColor: "#3085d6",
|
|
|
|
|
confirmButtonText: "OK",
|
|
|
|
|
}).then((result) => {
|
|
|
|
|
if (result.isConfirmed) {
|
|
|
|
|
router.push("/content-management/rewrite");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onSubmit(data: any) {
|
|
|
|
|
MySwal.fire({
|
|
|
|
|
title: "Simpan Data",
|
|
|
|
|
text: "",
|
|
|
|
|
icon: "warning",
|
|
|
|
|
showCancelButton: true,
|
|
|
|
|
cancelButtonColor: "#d33",
|
|
|
|
|
confirmButtonColor: "#3085d6",
|
|
|
|
|
confirmButtonText: "Simpan",
|
|
|
|
|
}).then((result) => {
|
|
|
|
|
if (result.isConfirmed) {
|
|
|
|
|
save(data);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-01-08 06:15:04 +00:00
|
|
|
|
2025-01-07 19:36:40 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
async function initState() {
|
2025-06-07 13:28:41 +00:00
|
|
|
loading();
|
2025-01-07 19:36:40 +00:00
|
|
|
setLoadingState(true);
|
2025-06-03 05:46:06 +00:00
|
|
|
const response = await getDetail(
|
|
|
|
|
id,
|
|
|
|
|
states == "polda" ? "polda" : "mabes"
|
|
|
|
|
);
|
2025-01-07 19:36:40 +00:00
|
|
|
console.log("Detail dataaaa ::", response);
|
|
|
|
|
if (response?.data?.data?.isActive == false) {
|
|
|
|
|
window.location.replace("/");
|
|
|
|
|
}
|
|
|
|
|
const responseGet = await getPublicSuggestionList(id?.split("-")?.[0]);
|
|
|
|
|
|
|
|
|
|
// close();
|
|
|
|
|
if (componentMounted) {
|
2025-01-08 06:15:04 +00:00
|
|
|
setValue("title", response?.data?.data?.title);
|
|
|
|
|
setValue("mainKeyword", response?.data?.data?.title);
|
2025-06-07 13:28:41 +00:00
|
|
|
setValue("description", response?.data?.data?.htmlDescription);
|
2025-01-10 03:30:32 +00:00
|
|
|
setContent(response?.data?.data);
|
|
|
|
|
setIsFromSPIT(response?.data?.data?.isFromSPIT);
|
2025-01-07 19:36:40 +00:00
|
|
|
setListSuggestion(responseGet?.data?.data);
|
2025-01-08 06:15:04 +00:00
|
|
|
console.log("data list file", response?.data?.data);
|
2025-01-10 03:30:32 +00:00
|
|
|
// const mainUrl = response?.data?.data?.files[0]?.url;
|
|
|
|
|
// const ticket = response?.data?.data?.files[0]?.ticket;
|
2025-01-07 19:36:40 +00:00
|
|
|
// const urlBlob = await getBlobContent(mainUrl, ticket);
|
|
|
|
|
setMain({
|
2025-01-10 03:30:32 +00:00
|
|
|
id: response?.data?.data?.files[0]?.id,
|
|
|
|
|
type: response?.data?.data?.fileType.name,
|
2025-06-03 05:46:06 +00:00
|
|
|
url:
|
|
|
|
|
Number(response?.data?.data?.fileType?.id) == 4
|
|
|
|
|
? response?.data?.data?.files[0]?.secondaryUrl
|
|
|
|
|
: response?.data?.data?.files[0]?.url,
|
2025-01-10 03:30:32 +00:00
|
|
|
thumbnailFileUrl: response?.data?.data?.files[0]?.thumbnailFileUrl,
|
|
|
|
|
names: response?.data?.data?.files[0]?.fileName,
|
|
|
|
|
format: response?.data?.data?.files[0]?.format,
|
|
|
|
|
widthPixel: response?.data?.data?.files[0]?.widthPixel,
|
|
|
|
|
heightPixel: response?.data?.data?.files[0]?.heightPixel,
|
|
|
|
|
size: response?.data?.data?.files[0]?.size,
|
|
|
|
|
caption: response?.data?.data?.files[0]?.caption,
|
2025-01-07 19:36:40 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Send Meta Data
|
|
|
|
|
const metaData = {
|
2025-01-10 03:30:32 +00:00
|
|
|
title: response?.data?.data?.title,
|
|
|
|
|
image: response?.data?.data?.thumbnailLink,
|
2025-01-07 19:36:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
setCookiesEncrypt("meta_data", metaData);
|
|
|
|
|
setLoadingState(false); // (2) write some value to state
|
|
|
|
|
// await new Promise(resolve => setTimeout(resolve, 1000)); // 2 sec
|
|
|
|
|
// setIdm();
|
2025-06-07 13:28:41 +00:00
|
|
|
close();
|
2025-01-07 19:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
// This code runs when component is unmounted
|
|
|
|
|
componentMounted = false; // (4) set it to false if we leave the page
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initState();
|
|
|
|
|
}, [id]);
|
|
|
|
|
|
|
|
|
|
const handleGenerateArtikel = async () => {
|
|
|
|
|
loading();
|
|
|
|
|
const request = {
|
2025-06-07 13:28:41 +00:00
|
|
|
style: "Professional",
|
2025-06-03 05:46:06 +00:00
|
|
|
lang: "id",
|
|
|
|
|
contextType: "text",
|
|
|
|
|
urlContext: null,
|
|
|
|
|
context: content?.description,
|
2025-01-07 19:36:40 +00:00
|
|
|
createdBy: roleId,
|
2025-06-03 05:46:06 +00:00
|
|
|
sentiment: "Humorous",
|
|
|
|
|
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
2025-01-07 19:36:40 +00:00
|
|
|
};
|
2025-01-08 06:15:04 +00:00
|
|
|
console.log("Request", request);
|
2025-06-03 05:46:06 +00:00
|
|
|
const res = await generateDataRewrite(request);
|
2025-01-07 19:36:40 +00:00
|
|
|
close();
|
|
|
|
|
|
|
|
|
|
if (res.error) {
|
|
|
|
|
console.error(res.message);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const newArticleId = res?.data?.data?.id;
|
|
|
|
|
setIsGeneratedArticle(true);
|
|
|
|
|
|
|
|
|
|
setArticleIds((prevIds: any) => {
|
2025-06-09 09:50:30 +00:00
|
|
|
if (prevIds.length < 3) {
|
2025-01-07 19:36:40 +00:00
|
|
|
return [...prevIds, newArticleId];
|
|
|
|
|
} else {
|
|
|
|
|
const updatedIds = [...prevIds];
|
2025-06-09 09:50:30 +00:00
|
|
|
updatedIds[2] = newArticleId;
|
2025-01-07 19:36:40 +00:00
|
|
|
return updatedIds;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Cookies.set("nulisAIArticleIdTemp", articleIds);
|
|
|
|
|
};
|
|
|
|
|
|
2025-01-08 06:15:04 +00:00
|
|
|
const handleArticleIdClick = async (id: string) => {
|
|
|
|
|
setIsLoadingData(true);
|
|
|
|
|
let retryCount = 0;
|
|
|
|
|
const maxRetries = 20;
|
|
|
|
|
|
|
|
|
|
try {
|
2025-01-09 01:59:46 +00:00
|
|
|
const waitForStatusUpdate: any = async () => {
|
2025-01-08 06:15:04 +00:00
|
|
|
while (retryCount < maxRetries) {
|
|
|
|
|
const res = await getDetailArticle(id);
|
|
|
|
|
const articleData = res?.data?.data;
|
2025-01-07 19:36:40 +00:00
|
|
|
|
2025-01-08 06:15:04 +00:00
|
|
|
if (articleData?.status === 2) {
|
|
|
|
|
return articleData;
|
|
|
|
|
}
|
2025-01-07 19:36:40 +00:00
|
|
|
|
2025-01-08 06:15:04 +00:00
|
|
|
retryCount++;
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new Error("Timeout: Artikel belum selesai diproses.");
|
|
|
|
|
};
|
|
|
|
|
const articleData = await waitForStatusUpdate();
|
2025-06-03 05:46:06 +00:00
|
|
|
const cleanArticleBody = articleData?.articleBody?.replace(
|
|
|
|
|
/<img[^>]*>/g,
|
|
|
|
|
""
|
|
|
|
|
);
|
2025-06-07 13:28:41 +00:00
|
|
|
console.log("lalalala", articleData);
|
2025-01-08 06:15:04 +00:00
|
|
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
|
|
|
|
setValue("description", cleanArticleBody || "");
|
|
|
|
|
setArticleBody(cleanArticleBody || "");
|
2025-01-09 01:59:46 +00:00
|
|
|
setDetailArticle(articleData);
|
2025-06-07 13:28:41 +00:00
|
|
|
// setSelectedArticleId(id);
|
|
|
|
|
console.log("idnya", id);
|
2025-01-08 06:15:04 +00:00
|
|
|
setArticleImages(articleImagesData || []);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error fetching article details:", error);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsLoadingData(false);
|
|
|
|
|
}
|
2025-01-07 19:36:40 +00:00
|
|
|
};
|
|
|
|
|
|
2025-01-07 11:52:16 +00:00
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<HeaderManagement />
|
2025-01-31 12:51:04 +00:00
|
|
|
<div className="flex flex-col lg:flex-row">
|
2025-01-07 11:52:16 +00:00
|
|
|
<SidebarManagement />
|
2025-01-31 12:51:04 +00:00
|
|
|
<div className="w-full lg:w-2/3 p-8 lg:p-12">
|
2025-01-07 11:52:16 +00:00
|
|
|
<div className="flex flex-col">
|
2025-07-06 09:23:45 +00:00
|
|
|
<div className="text-xl font-bold mb-5">{t("content", { defaultValue: "Content" })} Rewrite</div>
|
2025-01-07 11:52:16 +00:00
|
|
|
<div className="p-8 border border-black rounded-lg">
|
2025-01-07 19:36:40 +00:00
|
|
|
<form method="POST" onSubmit={handleSubmit(onSubmit)}>
|
2025-01-08 06:15:04 +00:00
|
|
|
{content && (
|
|
|
|
|
<div className="flex flex-col gap-2 ">
|
2025-01-31 12:51:04 +00:00
|
|
|
<div className="flex flex-col lg:flex-row gap-2">
|
2025-01-08 06:15:04 +00:00
|
|
|
<div className="gap-1 flex flex-col mb-3">
|
2025-07-06 09:23:45 +00:00
|
|
|
<p className="font-semibold">{t("language", { defaultValue: "Language" })}</p>
|
2025-06-03 05:46:06 +00:00
|
|
|
<Select
|
|
|
|
|
value={selectedLanguage}
|
|
|
|
|
onValueChange={setSelectedLanguage}
|
|
|
|
|
>
|
2025-01-31 12:51:04 +00:00
|
|
|
<SelectTrigger className="w-full lg:w-[180px]">
|
2025-07-06 09:23:45 +00:00
|
|
|
<SelectValue placeholder={t("selectLanguage", { defaultValue: "Select Language" })} />
|
2025-01-08 06:15:04 +00:00
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
<SelectGroup>
|
2025-07-06 09:23:45 +00:00
|
|
|
<SelectLabel>{t("selectLanguage", { defaultValue: "Select Language" })}</SelectLabel>
|
2025-01-08 06:15:04 +00:00
|
|
|
<SelectItem value="id">Indonesia</SelectItem>
|
|
|
|
|
<SelectItem value="en">English</SelectItem>
|
|
|
|
|
</SelectGroup>
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="gap-1 flex flex-col mb-3">
|
2025-07-06 09:23:45 +00:00
|
|
|
<p className="font-semibold">{t("contextType", { defaultValue: "Context Type" })}</p>
|
2025-06-03 05:46:06 +00:00
|
|
|
<Select
|
|
|
|
|
value={selectedContextType}
|
|
|
|
|
onValueChange={setSelectedContextType}
|
|
|
|
|
>
|
2025-01-31 12:51:04 +00:00
|
|
|
<SelectTrigger className="w-full lg:w-[180px]">
|
2025-07-06 09:23:45 +00:00
|
|
|
<SelectValue placeholder={t("selectContext", { defaultValue: "Select Context" })} />
|
2025-01-08 06:15:04 +00:00
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
<SelectGroup>
|
2025-07-06 09:23:45 +00:00
|
|
|
<SelectLabel>{t("selectContext", { defaultValue: "Select Context" })}</SelectLabel>
|
|
|
|
|
<SelectItem value="text">{t("text", { defaultValue: "Text" })}</SelectItem>
|
2025-06-03 05:46:06 +00:00
|
|
|
<SelectItem value="article">
|
2025-07-06 09:23:45 +00:00
|
|
|
{t("article", { defaultValue: "Article" })}
|
2025-06-03 05:46:06 +00:00
|
|
|
</SelectItem>
|
|
|
|
|
<SelectItem value="transcript">
|
2025-07-06 09:23:45 +00:00
|
|
|
{t("transcript", { defaultValue: "Transcript" })}
|
2025-06-03 05:46:06 +00:00
|
|
|
</SelectItem>
|
2025-01-08 06:15:04 +00:00
|
|
|
<SelectItem value="url">URL</SelectItem>
|
|
|
|
|
</SelectGroup>
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="gap-1 flex flex-col mb-3">
|
2025-07-06 09:23:45 +00:00
|
|
|
<p className="font-semibold">{t("writingStyle", { defaultValue: "Writing Style" })}</p>
|
2025-06-03 05:46:06 +00:00
|
|
|
<Select
|
|
|
|
|
value={selectedWritingStyle}
|
|
|
|
|
onValueChange={setSelectedWritingStyle}
|
|
|
|
|
>
|
2025-01-31 12:51:04 +00:00
|
|
|
<SelectTrigger className="w-full lg:w-[180px]">
|
2025-07-06 09:23:45 +00:00
|
|
|
<SelectValue placeholder={t("selectWriting", { defaultValue: "Select Writing" })} />
|
2025-01-08 06:15:04 +00:00
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
<SelectGroup>
|
2025-07-06 09:23:45 +00:00
|
|
|
<SelectLabel>{t("selectWriting", { defaultValue: "Select Writing" })}</SelectLabel>
|
2025-01-08 06:15:04 +00:00
|
|
|
<SelectItem value="firendly">Friendly</SelectItem>
|
2025-06-03 05:46:06 +00:00
|
|
|
<SelectItem value="profesional">
|
|
|
|
|
Profesional
|
|
|
|
|
</SelectItem>
|
|
|
|
|
<SelectItem value="informational">
|
|
|
|
|
Informational
|
|
|
|
|
</SelectItem>
|
2025-01-08 06:15:04 +00:00
|
|
|
<SelectItem value="neutral">Neutral</SelectItem>
|
|
|
|
|
<SelectItem value="witty">Witty</SelectItem>
|
|
|
|
|
</SelectGroup>
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="gap-1 flex flex-col mb-3">
|
2025-07-06 09:23:45 +00:00
|
|
|
<p className="font-semibold">{t("articleSize", { defaultValue: "Article Size" })}</p>
|
2025-06-03 05:46:06 +00:00
|
|
|
<Select
|
|
|
|
|
value={selectedSize}
|
|
|
|
|
onValueChange={setSelectedSize}
|
|
|
|
|
>
|
2025-01-31 12:51:04 +00:00
|
|
|
<SelectTrigger className="w-full lg:w-[180px]">
|
2025-07-06 09:23:45 +00:00
|
|
|
<SelectValue placeholder={t("selectSize", { defaultValue: "Select Size" })} />
|
2025-01-08 06:15:04 +00:00
|
|
|
</SelectTrigger>
|
|
|
|
|
<SelectContent>
|
|
|
|
|
<SelectGroup>
|
2025-07-06 09:23:45 +00:00
|
|
|
<SelectLabel>{t("selectSize", { defaultValue: "Select Size" })}</SelectLabel>
|
2025-06-03 05:46:06 +00:00
|
|
|
<SelectItem value="news">
|
|
|
|
|
News (300 - 900 words)
|
|
|
|
|
</SelectItem>
|
|
|
|
|
<SelectItem value="info">
|
|
|
|
|
Info (900 - 2000 words)
|
|
|
|
|
</SelectItem>
|
|
|
|
|
<SelectItem value="detail">
|
|
|
|
|
Detail (2000 - 5000 words)
|
|
|
|
|
</SelectItem>
|
2025-01-08 06:15:04 +00:00
|
|
|
</SelectGroup>
|
|
|
|
|
</SelectContent>
|
|
|
|
|
</Select>
|
|
|
|
|
</div>
|
2025-01-07 19:36:40 +00:00
|
|
|
</div>
|
2025-01-08 06:15:04 +00:00
|
|
|
<div className="mb-3">
|
2025-07-06 09:23:45 +00:00
|
|
|
<p className="font-semibold">{t("title", { defaultValue: "Title" })}</p>
|
2025-01-08 06:15:04 +00:00
|
|
|
<Controller
|
|
|
|
|
control={control}
|
|
|
|
|
name="title"
|
2025-06-03 05:46:06 +00:00
|
|
|
render={({ field: { onChange, value } }) => (
|
|
|
|
|
<Input
|
|
|
|
|
type="text"
|
|
|
|
|
className={`w-full border py-3 rounded-lg ${
|
|
|
|
|
errors.title ? "is-invalid" : ""
|
|
|
|
|
}`}
|
|
|
|
|
{...register("title")}
|
|
|
|
|
id="title"
|
|
|
|
|
value={value}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2025-01-08 06:15:04 +00:00
|
|
|
/>
|
2025-01-07 19:36:40 +00:00
|
|
|
</div>
|
2025-01-08 06:15:04 +00:00
|
|
|
<div className="mb-3">
|
2025-07-06 09:23:45 +00:00
|
|
|
<p className="font-semibold">{t("mainKeyword", { defaultValue: "Main Keyword" })}</p>
|
2025-01-08 06:15:04 +00:00
|
|
|
<Controller
|
|
|
|
|
control={control}
|
|
|
|
|
name="mainKeyword"
|
|
|
|
|
render={({ field: { onChange, value } }) => (
|
2025-06-03 05:46:06 +00:00
|
|
|
<Input
|
|
|
|
|
type="text"
|
|
|
|
|
className={`w-full border py-3 rounded-lg ${
|
|
|
|
|
errors.mainKeyword ? "is-invalid" : ""
|
|
|
|
|
}`}
|
|
|
|
|
{...register("mainKeyword")}
|
|
|
|
|
id="mainKeyword"
|
|
|
|
|
value={value}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
/>
|
2025-01-08 06:15:04 +00:00
|
|
|
)}
|
|
|
|
|
/>
|
2025-01-07 19:36:40 +00:00
|
|
|
</div>
|
2025-01-08 06:15:04 +00:00
|
|
|
<div className="mb-3">
|
2025-06-07 13:28:41 +00:00
|
|
|
<p className="font-semibold">Deskripsi</p>
|
2025-01-08 06:15:04 +00:00
|
|
|
<Controller
|
|
|
|
|
control={control}
|
2025-06-07 13:28:41 +00:00
|
|
|
name="description"
|
2025-01-08 06:15:04 +00:00
|
|
|
render={({ field: { onChange, value } }) => (
|
2025-06-07 13:28:41 +00:00
|
|
|
// <Textarea
|
|
|
|
|
// className="py-20"
|
|
|
|
|
// id="description"
|
|
|
|
|
// placeholder="Tuliskan kata kunci atau frasa yang relevan dengan blog Anda, lalu tekan enter"
|
|
|
|
|
// {...register("description")}
|
|
|
|
|
// onChange={onChange}
|
|
|
|
|
// value={value}
|
|
|
|
|
// />
|
|
|
|
|
<CustomEditor
|
2025-06-03 05:46:06 +00:00
|
|
|
onChange={onChange}
|
2025-06-07 13:28:41 +00:00
|
|
|
initialData={content?.htmlDescription}
|
2025-06-03 05:46:06 +00:00
|
|
|
/>
|
2025-01-08 06:15:04 +00:00
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="mb-4">
|
2025-06-03 05:46:06 +00:00
|
|
|
<a
|
|
|
|
|
onClick={handleGenerateArtikel}
|
|
|
|
|
className="text-blue-500 cursor-pointer hover:bg-blue-700 hover:text-white border border-blue-500 rounded-md p-2 text-sm lg:text-base"
|
|
|
|
|
>
|
2025-01-08 06:15:04 +00:00
|
|
|
Generate Artikel
|
|
|
|
|
</a>
|
|
|
|
|
{isGeneratedArticle && (
|
2025-06-09 09:50:30 +00:00
|
|
|
<div className="mt-3 pb-0 flex flex-row gap-3">
|
2025-01-08 06:15:04 +00:00
|
|
|
{articleIds.map((id: any, index: any) => (
|
|
|
|
|
<p
|
|
|
|
|
key={index}
|
2025-06-09 09:50:30 +00:00
|
|
|
className={` w-fit rounded-md p-3 mt-2 ${
|
2025-06-07 13:28:41 +00:00
|
|
|
Number(selectedArticleId) === Number(id)
|
|
|
|
|
? "text-white w-fit p-3 hover:text-white cursor-pointer bg-[#31ce36] border-[#31ce36]"
|
|
|
|
|
: "text-[#48abf7] p-3 hover:text-white hover:bg-[#48abf7] w-fit cursor-pointer border border-[#48abf7]"
|
2025-01-09 01:59:46 +00:00
|
|
|
}`}
|
2025-06-07 13:28:41 +00:00
|
|
|
onClick={() => {
|
|
|
|
|
handleArticleIdClick(id);
|
|
|
|
|
setSelectedArticleId(Number(id));
|
|
|
|
|
}}
|
2025-01-08 06:15:04 +00:00
|
|
|
>
|
2025-06-07 13:28:41 +00:00
|
|
|
Article {index + 1}
|
2025-01-08 06:15:04 +00:00
|
|
|
</p>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-01-07 19:36:40 +00:00
|
|
|
</div>
|
|
|
|
|
|
2025-01-08 06:15:04 +00:00
|
|
|
<div className=" mb-3">
|
2025-07-06 09:23:45 +00:00
|
|
|
<p className="font-semibold">{t("newDescription", { defaultValue: "New Description" })}</p>
|
2025-01-08 06:15:04 +00:00
|
|
|
<Controller
|
|
|
|
|
control={control}
|
|
|
|
|
name="description"
|
|
|
|
|
render={({ field: { onChange, value } }) =>
|
|
|
|
|
isLoadingData ? (
|
|
|
|
|
<div className="flex justify-center items-center h-40">
|
2025-06-03 05:46:06 +00:00
|
|
|
<p className="text-gray-500">
|
|
|
|
|
Loading Proses Data...
|
|
|
|
|
</p>
|
2025-01-08 06:15:04 +00:00
|
|
|
</div>
|
|
|
|
|
) : (
|
2025-06-03 05:46:06 +00:00
|
|
|
<CustomEditor
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
initialData={articleBody || value}
|
|
|
|
|
/>
|
2025-01-08 06:15:04 +00:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
/>
|
2025-06-03 05:46:06 +00:00
|
|
|
{articleBody === null || articleBody === "" ? (
|
|
|
|
|
<p className="text-red-400 px-0 text-sm">
|
|
|
|
|
Deskripsi tidak boleh kosong*
|
|
|
|
|
</p>
|
|
|
|
|
) : (
|
|
|
|
|
""
|
|
|
|
|
)}
|
2025-01-08 06:15:04 +00:00
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-row gap-3">
|
|
|
|
|
<Button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
router.back();
|
|
|
|
|
}}
|
2025-01-31 12:51:04 +00:00
|
|
|
className="border border-blue-400 hover:bg-blue-400 hover:text-white text-blue-400 text-sm lg:text-base"
|
2025-01-08 06:15:04 +00:00
|
|
|
>
|
2025-07-06 09:23:45 +00:00
|
|
|
{t("back", { defaultValue: "Back" })}
|
2025-01-08 06:15:04 +00:00
|
|
|
</Button>
|
2025-06-03 05:46:06 +00:00
|
|
|
<Button
|
|
|
|
|
type="submit"
|
|
|
|
|
className="border border-blue-500 bg-blue-500 text-sm lg:text-base text-white"
|
|
|
|
|
>
|
2025-07-06 09:23:45 +00:00
|
|
|
{t("save", { defaultValue: "Save" })}
|
2025-01-08 06:15:04 +00:00
|
|
|
</Button>
|
|
|
|
|
</div>
|
2025-01-07 11:52:16 +00:00
|
|
|
</div>
|
2025-01-08 06:15:04 +00:00
|
|
|
)}
|
2025-01-07 11:52:16 +00:00
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default page;
|