feat: fix rewrite section

This commit is contained in:
sabdayagra 2025-01-08 13:15:04 +07:00
parent b05884384e
commit ca14a7271a
1 changed files with 206 additions and 215 deletions

View File

@ -4,7 +4,7 @@ import HeaderManagement from "@/components/landing-page/header-management";
import SidebarManagement from "@/components/landing-page/sidebar-management"; import SidebarManagement from "@/components/landing-page/sidebar-management";
import { useRouter } from "@/i18n/routing"; import { useRouter } from "@/i18n/routing";
import { getCookiesDecrypt, setCookiesEncrypt } from "@/lib/utils"; import { getCookiesDecrypt, setCookiesEncrypt } from "@/lib/utils";
import { useSearchParams } from "next/navigation"; import { useParams, useSearchParams } from "next/navigation";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
@ -15,7 +15,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import CustomEditor from "@/components/editor/custom-editor"; import CustomEditor from "@/components/editor/custom-editor";
import { generateDataArticle, getDetailArticle } from "@/service/content/ai"; import { generateDataArticle, getDetailArticle } from "@/service/content/ai";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { error, loading } from "@/config/swal"; import { close, error, loading } from "@/config/swal";
import { saveContentRewrite } from "@/service/content/content"; import { saveContentRewrite } from "@/service/content/content";
import { getPublicSuggestionList } from "@/service/landing/landing"; import { getPublicSuggestionList } from "@/service/landing/landing";
import { getDetail } from "@/service/detail/detail"; import { getDetail } from "@/service/detail/detail";
@ -23,9 +23,13 @@ import { yupResolver } from "@hookform/resolvers/yup";
import * as Yup from "yup"; import * as Yup from "yup";
import { htmlToString } from "@/utils/globals"; import { htmlToString } from "@/utils/globals";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
const imageSchema = z.object({ const imageSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }), title: z.string().min(1, { message: "Judul diperlukan" }),
mainKeyword: z.string().min(1, { message: "Keyword diperlukan" }),
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." }), description: z.string().min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }),
creatorName: z.string().min(1, { message: "Creator diperlukan" }), creatorName: z.string().min(1, { message: "Creator diperlukan" }),
// tags: z.string().min(1, { message: "Judul diperlukan" }), // tags: z.string().min(1, { message: "Judul diperlukan" }),
@ -33,12 +37,12 @@ const imageSchema = z.object({
const page = (props: { states?: any }) => { const page = (props: { states?: any }) => {
const { states } = props; const { states } = props;
const [profile, setProfile] = useState();
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const router = useRouter(); const router = useRouter();
const [, setLoadingState] = useState(false); const [, setLoadingState] = useState(false);
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const id: any = searchParams?.get("title"); const getParams = useParams();
const id: any = getParams?.id;
const [content, setContent] = useState<any>([]); const [content, setContent] = useState<any>([]);
const [isFromSPIT, setIsFromSPIT] = useState(false); const [isFromSPIT, setIsFromSPIT] = useState(false);
const [listSuggestion, setListSuggestion] = useState(); const [listSuggestion, setListSuggestion] = useState();
@ -54,21 +58,22 @@ const page = (props: { states?: any }) => {
const [selectedContextType, setSelectedContextType] = useState(""); const [selectedContextType, setSelectedContextType] = useState("");
const [selectedLanguage, setSelectedLanguage] = useState(""); const [selectedLanguage, setSelectedLanguage] = useState("");
const [selectedTitle, setSelectedTitle] = useState(""); const [selectedTitle, setSelectedTitle] = useState("");
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
const [selectedSEO, setSelectedSEO] = useState("");
const [selectedSize, setSelectedSize] = useState(""); const [selectedSize, setSelectedSize] = useState("");
const [detailArticle, setDetailArticle] = useState<any>(null); const [detailArticle, setDetailArticle] = useState<any>(null);
const [contentType, setContentType] = useState("all");
const [isLoadingData, setIsLoadingData] = useState<boolean>(false); const [isLoadingData, setIsLoadingData] = useState<boolean>(false);
const [detailData, setDetailData] = useState<any>(null); const [detailData, setDetailData] = useState<any>(null);
const [articleImages, setArticleImages] = useState<string[]>([]); const [articleImages, setArticleImages] = useState<string[]>([]);
const userLevelId = getCookiesDecrypt("ulie"); const userLevelId = getCookiesDecrypt("ulie");
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
type ImageSchema = z.infer<typeof imageSchema>; type ImageSchema = z.infer<typeof imageSchema>;
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
title: Yup.string().required("Judul tidak boleh kosong"), title: Yup.string().required("Judul tidak boleh kosong"),
mainKeyword: Yup.string().required("Keyword tidak boleh kosong"),
seo: Yup.string().required("Tuliskan kata kunci atau frasa yang relevan dengan blog Anda, lalu tekan enter"),
description: Yup.string().required("Narasi Penugasan harus lebih dari 2 karakter."),
}); });
let componentMounted = true; let componentMounted = true;
@ -87,43 +92,9 @@ const page = (props: { states?: any }) => {
reset, reset,
formState: { errors }, formState: { errors },
setValue, setValue,
getValues,
} = useForm(formOptions); } = useForm(formOptions);
const handleArticleIdClick = async (id: string) => {
setIsLoadingData(true);
let retryCount = 0;
const maxRetries = 20;
try {
const waitForStatusUpdate = async () => {
while (retryCount < maxRetries) {
const res = await getDetailArticle(id);
const articleData = res?.data?.data;
if (articleData?.status === 2) {
return articleData;
}
retryCount++;
await new Promise((resolve) => setTimeout(resolve, 5000));
}
throw new Error("Timeout: Artikel belum selesai diproses.");
};
const articleData = await waitForStatusUpdate();
const cleanArticleBody = articleData?.articleBody?.replace(/<img[^>]*>/g, "");
const articleImagesData = articleData?.imagesUrl?.split(",");
setArticleBody(cleanArticleBody || "");
setDetailData(articleData);
setSelectedArticleId(id);
setArticleImages(articleImagesData || []);
} catch (error) {
console.error("Error fetching article details:", error);
} finally {
setIsLoadingData(false);
}
};
const save = async (data: any) => { const save = async (data: any) => {
const request = { const request = {
title: data.title, title: data.title,
@ -176,6 +147,7 @@ const page = (props: { states?: any }) => {
} }
}); });
} }
useEffect(() => { useEffect(() => {
async function initState() { async function initState() {
setLoadingState(true); setLoadingState(true);
@ -188,10 +160,13 @@ const page = (props: { states?: any }) => {
// close(); // close();
if (componentMounted) { if (componentMounted) {
setValue("title", response?.data?.data?.title);
setValue("mainKeyword", response?.data?.data?.title);
setValue("seo", response?.data?.data?.description);
setContent(response?.data.data); setContent(response?.data.data);
setIsFromSPIT(response?.data.data?.isFromSPIT); setIsFromSPIT(response?.data.data?.isFromSPIT);
setListSuggestion(responseGet?.data?.data); setListSuggestion(responseGet?.data?.data);
console.log("data list file", response?.data.data?.files); console.log("data list file", response?.data?.data);
// const mainUrl = response?.data.data?.files[0]?.url; // const mainUrl = response?.data.data?.files[0]?.url;
// const ticket = response?.data.data?.files[0]?.ticket; // const ticket = response?.data.data?.files[0]?.ticket;
// const urlBlob = await getBlobContent(mainUrl, ticket); // const urlBlob = await getBlobContent(mainUrl, ticket);
@ -232,23 +207,24 @@ const page = (props: { states?: any }) => {
const handleGenerateArtikel = async () => { const handleGenerateArtikel = async () => {
loading(); loading();
const request = { const request = {
advConfig: selectedAdvConfig, advConfig: "",
style: selectedWritingStyle, style: selectedWritingStyle,
website: "None", website: "None",
connectToWeb: true, connectToWeb: true,
lang: selectedLanguage, lang: selectedLanguage,
pointOfView: "None", pointOfView: "None",
title: content?.title, title: getValues("title"),
imageSource: "Web", imageSource: "Web",
mainKeyword: content?.title, mainKeyword: getValues("mainKeyword"),
additionalKeywords: content?.htmlDescription, additionalKeywords: getValues("seo"),
targetCountry: null, targetCountry: null,
articleSize: selectedSize, articleSize: selectedSize,
projectId: 2, projectId: 2,
createdBy: roleId, createdBy: roleId,
clientId: "ngDLPPiorplznw2jTqVe3YFCz5xqKfUJ", // clientId: "ngDLPPiorplznw2jTqVe3YFCz5xqKfUJ",
clientId: "mediahubClientId",
}; };
console.log("Request", request);
const res = await generateDataArticle(request); const res = await generateDataArticle(request);
close(); close();
@ -273,17 +249,41 @@ const page = (props: { states?: any }) => {
Cookies.set("nulisAIArticleIdTemp", articleIds); Cookies.set("nulisAIArticleIdTemp", articleIds);
}; };
const handleArticleClick = async (id: any) => { const handleArticleIdClick = async (id: string) => {
setIsLoadingData(true);
let retryCount = 0;
const maxRetries = 20;
try {
const waitForStatusUpdate = async () => {
while (retryCount < maxRetries) {
const res = await getDetailArticle(id); const res = await getDetailArticle(id);
const articleData = res?.data?.data; const articleData = res?.data?.data;
if (articleData?.status === 2) {
return articleData;
}
retryCount++;
await new Promise((resolve) => setTimeout(resolve, 5000));
}
throw new Error("Timeout: Artikel belum selesai diproses.");
};
const articleData = await waitForStatusUpdate();
const cleanArticleBody = articleData?.articleBody?.replace(/<img[^>]*>/g, ""); const cleanArticleBody = articleData?.articleBody?.replace(/<img[^>]*>/g, "");
console.log("lalalala", cleanArticleBody);
const articleImagesData = articleData?.imagesUrl?.split(","); // Split URLs into an array const articleImagesData = articleData?.imagesUrl?.split(",");
setValue("description", cleanArticleBody || "");
setArticleBody(cleanArticleBody || ""); // Set articleBody for CKEditor setArticleBody(cleanArticleBody || "");
setDetailArticle(articleData); setDetailData(articleData);
setSelectedArticleId(id); setSelectedArticleId(id);
// setArticleImages(articleImagesData || []); // Set images array in state setArticleImages(articleImagesData || []);
} catch (error) {
console.error("Error fetching article details:", error);
} finally {
setIsLoadingData(false);
}
}; };
return ( return (
@ -297,27 +297,27 @@ const page = (props: { states?: any }) => {
<div className="text-xl font-bold mb-5">Content Rewrite</div> <div className="text-xl font-bold mb-5">Content Rewrite</div>
<div className="p-8 border border-black rounded-lg"> <div className="p-8 border border-black rounded-lg">
<form method="POST" onSubmit={handleSubmit(onSubmit)}> <form method="POST" onSubmit={handleSubmit(onSubmit)}>
{/* {content && ( */} {content && (
<div className="flex flex-col gap-2 "> <div className="flex flex-col gap-2 ">
<div className="flex flex-row gap-2"> <div className="flex flex-row gap-2">
<div className="gap-1 flex flex-col mb-3"> <div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">Bahasa</p> <p className="font-semibold">Bahasa</p>
<Select value={selectedLanguage} onValueChange={(e: any) => setSelectedLanguage(e.target.value)}> <Select value={selectedLanguage} onValueChange={setSelectedLanguage}>
<SelectTrigger className="w-[180px]"> <SelectTrigger className="w-[180px]">
<SelectValue placeholder="Pilih Bahasa" /> <SelectValue placeholder="Pilih Bahasa" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectGroup> <SelectGroup>
<SelectLabel>Pilih Bahasa</SelectLabel> <SelectLabel>Pilih Bahasa</SelectLabel>
<SelectItem value="indonesia">Indonesia</SelectItem> <SelectItem value="id">Indonesia</SelectItem>
<SelectItem value="english">English</SelectItem> <SelectItem value="en">English</SelectItem>
</SelectGroup> </SelectGroup>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
<div className="gap-1 flex flex-col mb-3"> <div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">Context Type</p> <p className="font-semibold">Context Type</p>
<Select value={selectedContextType} onValueChange={(e: any) => setSelectedContextType(e.target.value)}> <Select value={selectedContextType} onValueChange={setSelectedContextType}>
<SelectTrigger className="w-[180px]"> <SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select Context" /> <SelectValue placeholder="Select Context" />
</SelectTrigger> </SelectTrigger>
@ -334,7 +334,7 @@ const page = (props: { states?: any }) => {
</div> </div>
<div className="gap-1 flex flex-col mb-3"> <div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">Writing Style</p> <p className="font-semibold">Writing Style</p>
<Select value={selectedWritingStyle} onValueChange={(e: any) => setSelectedWritingStyle(e.target.value)}> <Select value={selectedWritingStyle} onValueChange={setSelectedWritingStyle}>
<SelectTrigger className="w-[180px]"> <SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select Writing" /> <SelectValue placeholder="Select Writing" />
</SelectTrigger> </SelectTrigger>
@ -352,7 +352,7 @@ const page = (props: { states?: any }) => {
</div> </div>
<div className="gap-1 flex flex-col mb-3"> <div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">Article Size</p> <p className="font-semibold">Article Size</p>
<Select value={selectedSize} onValueChange={(e: any) => setSelectedSize(e.target.value)}> <Select value={selectedSize} onValueChange={setSelectedSize}>
<SelectTrigger className="w-[180px]"> <SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select Size" /> <SelectValue placeholder="Select Size" />
</SelectTrigger> </SelectTrigger>
@ -367,61 +367,53 @@ const page = (props: { states?: any }) => {
</Select> </Select>
</div> </div>
</div> </div>
<div className="mb-3"> <div className="mb-3">
<p className="font-semibold">Judul</p> <p className="font-semibold">Judul</p>
<input <Controller
type="text" control={control}
// className="w-full border py-3 rounded-lg" name="title"
className={`w-full border py-3 rounded-lg ${errors.title ? "is-invalid" : ""}`} 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} />}
{...register("title", {
value: content?.title,
})}
id="title"
defaultValue={content?.title}
// onChange={(e) => setSelectedTitle(e.target.value)}
/> />
</div> </div>
<div className="mb-3"> <div className="mb-3">
<p className="font-semibold">Main Keyword</p> <p className="font-semibold">Main Keyword</p>
<input <Controller
type="text" control={control}
className="w-full border py-3 rounded-lg mb-4"
id="mainKeyword"
name="mainKeyword" name="mainKeyword"
// onChange={(e) => render={({ field: { onChange, value } }) => (
// setSelectedMainKeyword(e.target.value) <Input type="text" className={`w-full border py-3 rounded-lg ${errors.mainKeyword ? "is-invalid" : ""}`} {...register("mainKeyword")} id="mainKeyword" value={value} onChange={onChange} />
// } )}
placeholder="Masukan Main Keyword disini!"
defaultValue={content?.title}
/> />
</div> </div>
<div className="mb-3"> <div className="mb-3">
<p className="font-semibold">SEO</p> <p className="font-semibold">SEO</p>
<textarea <Controller
className="border py-15 w-full rounded-lg" control={control}
id="seo"
name="seo" name="seo"
placeholder="Tuliskan kata kunci atau frasa yang relevan dengan blog Anda, lalu tekan enter" render={({ field: { onChange, value } }) => (
// value={selectedSEO} <Textarea className="py-20" id="seo" placeholder="Tuliskan kata kunci atau frasa yang relevan dengan blog Anda, lalu tekan enter" {...register("seo")} onChange={onChange} value={value} />
// onChange={(e) => setSelectedSEO(e.target.value)} )}
defaultValue={htmlToString(content?.htmlDescription)}
/> />
</div> </div>
<div className="mb-4"> <div className="mb-4">
<a onClick={handleGenerateArtikel} className="text-blue-500 hover:bg-blue-700 hover:text-white border border-blue-500 rounded-md p-2"> <a onClick={handleGenerateArtikel} className="text-blue-500 cursor-pointer hover:bg-blue-700 hover:text-white border border-blue-500 rounded-md p-2">
Generate Artikel Generate Artikel
</a> </a>
{isGeneratedArticle && ( {isGeneratedArticle && (
<div className="mt-3 ml-2 pb-0"> <div className="mt-3 ml-2 pb-0">
{articleIds.map((id: any, index: any) => ( {articleIds.map((id: any, index: any) => (
<p key={index} className={`text-black m-1 ${selectedArticleId === id ? "bg-[#31ce36] border border-[#31ce36]" : "bg-[#48abf7] border border-[#48abf7]"}`} onClick={() => handleArticleClick(id)}> <p
key={index}
className={`text-black m-1 ${selectedArticleId === id ? "bg-[#31ce36] cursor-pointer border border-[#31ce36]" : "bg-[#48abf7] cursor-pointer border border-[#48abf7]"}`}
onClick={() => handleArticleIdClick(id)}
>
{id} {id}
</p> </p>
))} ))}
</div> </div>
)} )}
</div> </div>
<div className=" mb-3"> <div className=" mb-3">
<p className="font-semibold">Deskripsi Baru</p> <p className="font-semibold">Deskripsi Baru</p>
<Controller <Controller
@ -433,7 +425,7 @@ const page = (props: { states?: any }) => {
<p className="text-gray-500">Loading Proses Data...</p> <p className="text-gray-500">Loading Proses Data...</p>
</div> </div>
) : ( ) : (
<CustomEditor onChange={(event: any) => setArticleBody(event.editor.getData())} initialData={articleBody || value} /> <CustomEditor onChange={onChange} initialData={articleBody || value} />
) )
} }
/> />
@ -441,21 +433,20 @@ const page = (props: { states?: any }) => {
</div> </div>
<div className="flex flex-row gap-3"> <div className="flex flex-row gap-3">
<Button <Button
onClick={(e) => { type="button"
e.preventDefault(); onClick={() => {
window.close(); router.back();
}} }}
className="border border-blue-400 hover:bg-blue-400 hover:text-white text-blue-400" className="border border-blue-400 hover:bg-blue-400 hover:text-white text-blue-400"
> >
Batal Kembali
</Button> </Button>
<Button type="submit" className="border border-blue-500 bg-blue-500 text-white"> <Button type="submit" className="border border-blue-500 bg-blue-500 text-white">
Simpan Simpan
</Button> </Button>
</div> </div>
</div> </div>
)}
{/* )} */}
</form> </form>
</div> </div>
</div> </div>