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" ;
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" ;
import CustomEditor from "@/components/editor/custom-editor" ;
import { generateDataArticle , getDetailArticle } from "@/service/content/ai" ;
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 { htmlToString } from "@/utils/globals" ;
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-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" } ) ,
seo : z.string ( ) . min ( 1 , { message : "Tuliskan kata kunci atau frasa yang relevan dengan blog Anda, lalu tekan enter" } ) ,
2025-01-07 19:36:40 +00:00
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" }),
} ) ;
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 ( "" ) ;
const [ selectedWritingStyle , setSelectedWritingStyle ] = useState ( "" ) ;
const [ selectedContextType , setSelectedContextType ] = useState ( "" ) ;
const [ selectedLanguage , setSelectedLanguage ] = useState ( "" ) ;
const [ selectedTitle , setSelectedTitle ] = useState ( "" ) ;
const [ selectedSize , setSelectedSize ] = useState ( "" ) ;
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-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" ) ,
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." ) ,
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() {
setLoadingState ( true ) ;
const response = await getDetail ( id , states == "polda" ? "polda" : "mabes" ) ;
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 ) ;
setValue ( "seo" , response ? . data ? . data ? . description ) ;
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 ,
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 ,
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();
}
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-01-08 06:15:04 +00:00
advConfig : "" ,
2025-01-07 19:36:40 +00:00
style : selectedWritingStyle ,
website : "None" ,
connectToWeb : true ,
lang : selectedLanguage ,
pointOfView : "None" ,
2025-01-08 06:15:04 +00:00
title : getValues ( "title" ) ,
2025-01-07 19:36:40 +00:00
imageSource : "Web" ,
2025-01-08 06:15:04 +00:00
mainKeyword : getValues ( "mainKeyword" ) ,
additionalKeywords : getValues ( "seo" ) ,
2025-01-07 19:36:40 +00:00
targetCountry : null ,
articleSize : selectedSize ,
projectId : 2 ,
createdBy : roleId ,
2025-01-08 06:15:04 +00:00
// clientId: "ngDLPPiorplznw2jTqVe3YFCz5xqKfUJ",
clientId : "mediahubClientId" ,
2025-01-07 19:36:40 +00:00
} ;
2025-01-08 06:15:04 +00:00
console . log ( "Request" , request ) ;
2025-01-07 19:36:40 +00:00
const res = await generateDataArticle ( request ) ;
close ( ) ;
if ( res . error ) {
console . error ( res . message ) ;
return false ;
}
const newArticleId = res ? . data ? . data ? . id ;
setIsGeneratedArticle ( true ) ;
setArticleIds ( ( prevIds : any ) = > {
if ( prevIds . length < 5 ) {
return [ . . . prevIds , newArticleId ] ;
} else {
const updatedIds = [ . . . prevIds ] ;
updatedIds [ 4 ] = newArticleId ;
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 ( ) ;
const cleanArticleBody = articleData ? . articleBody ? . replace ( /<img[^>]*>/g , "" ) ;
console . log ( "lalalala" , cleanArticleBody ) ;
const articleImagesData = articleData ? . imagesUrl ? . split ( "," ) ;
setValue ( "description" , cleanArticleBody || "" ) ;
setArticleBody ( cleanArticleBody || "" ) ;
2025-01-09 01:59:46 +00:00
setDetailArticle ( articleData ) ;
2025-01-08 06:15:04 +00:00
setSelectedArticleId ( id ) ;
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" >
< div className = "text-xl font-bold mb-5" > Content Rewrite < / div >
< 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" >
< p className = "font-semibold" > Bahasa < / p >
< Select value = { selectedLanguage } onValueChange = { setSelectedLanguage } >
2025-01-31 12:51:04 +00:00
< SelectTrigger className = "w-full lg:w-[180px]" >
2025-01-08 06:15:04 +00:00
< SelectValue placeholder = "Pilih Bahasa" / >
< / SelectTrigger >
< SelectContent >
< SelectGroup >
< SelectLabel > Pilih Bahasa < / SelectLabel >
< SelectItem value = "id" > Indonesia < / SelectItem >
< SelectItem value = "en" > English < / SelectItem >
< / SelectGroup >
< / SelectContent >
< / Select >
< / div >
< div className = "gap-1 flex flex-col mb-3" >
< p className = "font-semibold" > Context Type < / p >
< Select value = { selectedContextType } onValueChange = { setSelectedContextType } >
2025-01-31 12:51:04 +00:00
< SelectTrigger className = "w-full lg:w-[180px]" >
2025-01-08 06:15:04 +00:00
< SelectValue placeholder = "Select Context" / >
< / SelectTrigger >
< SelectContent >
< SelectGroup >
< SelectLabel > Select Context Type < / SelectLabel >
< SelectItem value = "text" > Text < / SelectItem >
< SelectItem value = "article" > Article < / SelectItem >
< SelectItem value = "transcript" > Transcript < / SelectItem >
< SelectItem value = "url" > URL < / SelectItem >
< / SelectGroup >
< / SelectContent >
< / Select >
< / div >
< div className = "gap-1 flex flex-col mb-3" >
< p className = "font-semibold" > Writing Style < / p >
< Select value = { selectedWritingStyle } onValueChange = { setSelectedWritingStyle } >
2025-01-31 12:51:04 +00:00
< SelectTrigger className = "w-full lg:w-[180px]" >
2025-01-08 06:15:04 +00:00
< SelectValue placeholder = "Select Writing" / >
< / SelectTrigger >
< SelectContent >
< SelectGroup >
< SelectLabel > Select Writing Style < / SelectLabel >
< SelectItem value = "firendly" > Friendly < / SelectItem >
< SelectItem value = "profesional" > Profesional < / SelectItem >
< SelectItem value = "informational" > Informational < / SelectItem >
< SelectItem value = "neutral" > Neutral < / SelectItem >
< SelectItem value = "witty" > Witty < / SelectItem >
< / SelectGroup >
< / SelectContent >
< / Select >
< / div >
< div className = "gap-1 flex flex-col mb-3" >
< p className = "font-semibold" > Article Size < / p >
< Select value = { selectedSize } onValueChange = { setSelectedSize } >
2025-01-31 12:51:04 +00:00
< SelectTrigger className = "w-full lg:w-[180px]" >
2025-01-08 06:15:04 +00:00
< SelectValue placeholder = "Select Size" / >
< / SelectTrigger >
< SelectContent >
< SelectGroup >
< SelectLabel > Select Article Size < / 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 >
< / 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" >
< p className = "font-semibold" > Judul < / p >
< 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 } / > }
/ >
2025-01-07 19:36:40 +00:00
< / div >
2025-01-08 06:15:04 +00:00
< div className = "mb-3" >
< p className = "font-semibold" > Main Keyword < / p >
< Controller
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 } / >
) }
/ >
2025-01-07 19:36:40 +00:00
< / div >
2025-01-08 06:15:04 +00:00
< div className = "mb-3" >
< p className = "font-semibold" > SEO < / p >
< Controller
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 } / >
) }
/ >
< / div >
< div className = "mb-4" >
2025-01-31 12:51:04 +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 && (
< div className = "mt-3 ml-2 pb-0" >
{ articleIds . map ( ( id : any , index : any ) = > (
< p
key = { index }
2025-01-09 01:59:46 +00:00
className = { ` text-black border border-black w-fit rounded-md p-3 m-1 ${
selectedArticleId === id
? "text-[#31ce36] w-fit p-3 hover:bg-[#31ce36] hover:text-white cursor-pointer border border-[#31ce36]"
: "text-[#48abf7] p-3 hover:text-white hover:bg-[#48abf7] w-fit cursor-pointer border border-[#48abf7]"
} ` }
2025-01-08 06:15:04 +00:00
onClick = { ( ) = > handleArticleIdClick ( id ) }
>
{ id }
< / p >
) ) }
< / div >
) }
2025-01-07 19:36:40 +00:00
< / div >
2025-01-08 06:15:04 +00:00
< div className = " mb-3" >
< p className = "font-semibold" > Deskripsi Baru < / p >
< Controller
control = { control }
name = "description"
render = { ( { field : { onChange , value } } ) = >
isLoadingData ? (
< div className = "flex justify-center items-center h-40" >
< p className = "text-gray-500" > Loading Proses Data . . . < / p >
< / div >
) : (
< CustomEditor onChange = { onChange } initialData = { articleBody || value } / >
)
}
/ >
2025-01-09 01:59:46 +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
>
Kembali
< / Button >
2025-01-31 12:51:04 +00:00
< Button type = "submit" className = "border border-blue-500 bg-blue-500 text-sm lg:text-base text-white" >
2025-01-08 06:15:04 +00:00
Simpan
< / 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 ;