feat:update content-rewrite

This commit is contained in:
Anang Yusman 2025-06-03 13:46:06 +08:00
parent 649aa4c638
commit 882c77b96f
4 changed files with 148 additions and 52 deletions

View File

@ -8,12 +8,24 @@ import { useParams, useSearchParams } from "next/navigation";
import React, { useEffect, useState } from "react";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Controller, useForm } from "react-hook-form";
import * as z from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import CustomEditor from "@/components/editor/custom-editor";
import { generateDataArticle, getDetailArticle } from "@/service/content/ai";
import {
generateDataArticle,
generateDataRewrite,
getDetailArticle,
} from "@/service/content/ai";
import { Button } from "@/components/ui/button";
import { close, error, loading } from "@/config/swal";
import { saveContentRewrite } from "@/service/content/content";
@ -29,8 +41,13 @@ import { useTranslations } from "next-intl";
const imageSchema = z.object({
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." }),
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." }),
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
// tags: z.string().min(1, { message: "Judul diperlukan" }),
});
@ -73,8 +90,12 @@ const page = (props: any) => {
const validationSchema = Yup.object().shape({
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."),
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;
@ -152,7 +173,10 @@ const page = (props: any) => {
useEffect(() => {
async function initState() {
setLoadingState(true);
const response = await getDetail(id, states == "polda" ? "polda" : "mabes");
const response = await getDetail(
id,
states == "polda" ? "polda" : "mabes"
);
console.log("Detail dataaaa ::", response);
if (response?.data?.data?.isActive == false) {
window.location.replace("/");
@ -174,7 +198,10 @@ const page = (props: any) => {
setMain({
id: response?.data?.data?.files[0]?.id,
type: response?.data?.data?.fileType.name,
url: Number(response?.data?.data?.fileType?.id) == 4 ? response?.data?.data?.files[0]?.secondaryUrl : response?.data?.data?.files[0]?.url,
url:
Number(response?.data?.data?.fileType?.id) == 4
? response?.data?.data?.files[0]?.secondaryUrl
: response?.data?.data?.files[0]?.url,
thumbnailFileUrl: response?.data?.data?.files[0]?.thumbnailFileUrl,
names: response?.data?.data?.files[0]?.fileName,
format: response?.data?.data?.files[0]?.format,
@ -208,25 +235,17 @@ const page = (props: any) => {
const handleGenerateArtikel = async () => {
loading();
const request = {
advConfig: "",
style: selectedWritingStyle,
website: "None",
connectToWeb: true,
lang: selectedLanguage,
pointOfView: "None",
title: getValues("title"),
imageSource: "Web",
mainKeyword: getValues("mainKeyword"),
additionalKeywords: getValues("seo"),
targetCountry: null,
articleSize: selectedSize,
projectId: 2,
style: "friendly",
lang: "id",
contextType: "text",
urlContext: null,
context: content?.description,
createdBy: roleId,
// clientId: "ngDLPPiorplznw2jTqVe3YFCz5xqKfUJ",
clientId: "mediahubClientId",
sentiment: "Humorous",
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
};
console.log("Request", request);
const res = await generateDataArticle(request);
const res = await generateDataRewrite(request);
close();
if (res.error) {
@ -272,7 +291,10 @@ const page = (props: any) => {
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(",");
setValue("description", cleanArticleBody || "");
@ -302,7 +324,10 @@ const page = (props: any) => {
<div className="flex flex-col lg:flex-row gap-2">
<div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">{t("language")}</p>
<Select value={selectedLanguage} onValueChange={setSelectedLanguage}>
<Select
value={selectedLanguage}
onValueChange={setSelectedLanguage}
>
<SelectTrigger className="w-full lg:w-[180px]">
<SelectValue placeholder={t("selectLanguage")} />
</SelectTrigger>
@ -317,7 +342,10 @@ const page = (props: any) => {
</div>
<div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">{t("contextType")}</p>
<Select value={selectedContextType} onValueChange={setSelectedContextType}>
<Select
value={selectedContextType}
onValueChange={setSelectedContextType}
>
<SelectTrigger className="w-full lg:w-[180px]">
<SelectValue placeholder={t("selectContext")} />
</SelectTrigger>
@ -325,8 +353,12 @@ const page = (props: any) => {
<SelectGroup>
<SelectLabel>{t("selectContext")}</SelectLabel>
<SelectItem value="text">{t("text")}</SelectItem>
<SelectItem value="article">{t("article")}</SelectItem>
<SelectItem value="transcript">{t("transcript")}</SelectItem>
<SelectItem value="article">
{t("article")}
</SelectItem>
<SelectItem value="transcript">
{t("transcript")}
</SelectItem>
<SelectItem value="url">URL</SelectItem>
</SelectGroup>
</SelectContent>
@ -334,7 +366,10 @@ const page = (props: any) => {
</div>
<div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">{t("writingStyle")}</p>
<Select value={selectedWritingStyle} onValueChange={setSelectedWritingStyle}>
<Select
value={selectedWritingStyle}
onValueChange={setSelectedWritingStyle}
>
<SelectTrigger className="w-full lg:w-[180px]">
<SelectValue placeholder={t("selectWriting")} />
</SelectTrigger>
@ -342,8 +377,12 @@ const page = (props: any) => {
<SelectGroup>
<SelectLabel>{t("selectWriting")}</SelectLabel>
<SelectItem value="firendly">Friendly</SelectItem>
<SelectItem value="profesional">Profesional</SelectItem>
<SelectItem value="informational">Informational</SelectItem>
<SelectItem value="profesional">
Profesional
</SelectItem>
<SelectItem value="informational">
Informational
</SelectItem>
<SelectItem value="neutral">Neutral</SelectItem>
<SelectItem value="witty">Witty</SelectItem>
</SelectGroup>
@ -352,16 +391,25 @@ const page = (props: any) => {
</div>
<div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">{t("articleSize")}</p>
<Select value={selectedSize} onValueChange={setSelectedSize}>
<Select
value={selectedSize}
onValueChange={setSelectedSize}
>
<SelectTrigger className="w-full lg:w-[180px]">
<SelectValue placeholder={t("selectSize")} />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>{t("selectSize")}</SelectLabel>
<SelectItem value="news">News (300 - 900 words)</SelectItem>
<SelectItem value="info">Info (900 - 2000 words)</SelectItem>
<SelectItem value="detail">Detail (2000 - 5000 words)</SelectItem>
<SelectItem value="news">
News (300 - 900 words)
</SelectItem>
<SelectItem value="info">
Info (900 - 2000 words)
</SelectItem>
<SelectItem value="detail">
Detail (2000 - 5000 words)
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
@ -372,7 +420,18 @@ const page = (props: any) => {
<Controller
control={control}
name="title"
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} />}
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}
/>
)}
/>
</div>
<div className="mb-3">
@ -381,7 +440,16 @@ const page = (props: any) => {
control={control}
name="mainKeyword"
render={({ field: { onChange, value } }) => (
<Input type="text" className={`w-full border py-3 rounded-lg ${errors.mainKeyword ? "is-invalid" : ""}`} {...register("mainKeyword")} id="mainKeyword" value={value} onChange={onChange} />
<Input
type="text"
className={`w-full border py-3 rounded-lg ${
errors.mainKeyword ? "is-invalid" : ""
}`}
{...register("mainKeyword")}
id="mainKeyword"
value={value}
onChange={onChange}
/>
)}
/>
</div>
@ -391,12 +459,22 @@ const page = (props: any) => {
control={control}
name="seo"
render={({ field: { onChange, value } }) => (
<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} />
<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}
/>
)}
/>
</div>
<div className="mb-4">
<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">
<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"
>
Generate Artikel
</a>
{isGeneratedArticle && (
@ -426,14 +504,25 @@ const page = (props: any) => {
render={({ field: { onChange, value } }) =>
isLoadingData ? (
<div className="flex justify-center items-center h-40">
<p className="text-gray-500">Loading Proses Data...</p>
<p className="text-gray-500">
Loading Proses Data...
</p>
</div>
) : (
<CustomEditor onChange={onChange} initialData={articleBody || value} />
<CustomEditor
onChange={onChange}
initialData={articleBody || value}
/>
)
}
/>
{articleBody === null || articleBody === "" ? <p className="text-red-400 px-0 text-sm">Deskripsi tidak boleh kosong*</p> : ""}
{articleBody === null || articleBody === "" ? (
<p className="text-red-400 px-0 text-sm">
Deskripsi tidak boleh kosong*
</p>
) : (
""
)}
</div>
<div className="flex flex-row gap-3">
<Button
@ -445,7 +534,10 @@ const page = (props: any) => {
>
{t("back")}
</Button>
<Button type="submit" className="border border-blue-500 bg-blue-500 text-sm lg:text-base text-white">
<Button
type="submit"
className="border border-blue-500 bg-blue-500 text-sm lg:text-base text-white"
>
{t("save")}
</Button>
</div>

View File

@ -283,7 +283,7 @@ const page = () => {
</p>
</div>
<Link
href={`/content-management/rewrite/create/${image?.id}`}
href={`/content-management/rewrite/create/${image?.mediaUploadId}`}
className="flex flex-row hover:text-red-800 gap-2"
>
<Icon icon="jam:write" fontSize={25} />

View File

@ -1,6 +1,10 @@
import { httpDeleteInterceptor, httpGetInterceptor, httpPostInterceptor } from "../http-config/http-interceptor-service";
import {
httpDeleteInterceptor,
httpGetInterceptor,
httpPostInterceptor,
} from "../http-config/http-interceptor-service";
export async function getDetail(id: any, state: any) {
const url = `media/public?slug=${id}&state=${state}`;
export async function getDetail(slug: any, state: any) {
const url = `media/public?slug=${slug}&state=${state}`;
return httpGetInterceptor(url);
}

View File

@ -228,10 +228,10 @@ export async function saveWishlist(data: { mediaUploadId: string }) {
export async function getPublicSuggestionList(slug: any) {
const url = `media/public/suggestion?mediaId=${slug}`;
const headers = {
"content-Type": "application/json",
};
return httpGet(url, headers);
// const headers = {
// "content-Type": "application/json",
// };
return httpGetInterceptor(url);
}
export async function getUserNotifications(page = 0, typeId: any) {