fix: translate button in approver-int
This commit is contained in:
parent
d9475cc0a9
commit
73c56e764d
|
|
@ -44,13 +44,14 @@ import {
|
||||||
getDetailArticle,
|
getDetailArticle,
|
||||||
getGenerateKeywords,
|
getGenerateKeywords,
|
||||||
getGenerateTitle,
|
getGenerateTitle,
|
||||||
|
translateText,
|
||||||
} from "@/service/content/ai";
|
} from "@/service/content/ai";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import { useDropzone } from "react-dropzone";
|
import { useDropzone } from "react-dropzone";
|
||||||
import { Icon } from "@iconify/react";
|
import { Icon } from "@iconify/react";
|
||||||
import { CloudUpload } from "lucide-react";
|
import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { error, loading } from "@/config/swal";
|
import { close, error, loading } from "@/config/swal";
|
||||||
import { Item } from "@radix-ui/react-dropdown-menu";
|
import { Item } from "@radix-ui/react-dropdown-menu";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { getCsrfToken } from "@/service/auth";
|
import { getCsrfToken } from "@/service/auth";
|
||||||
|
|
@ -145,6 +146,10 @@ export default function FormAudio() {
|
||||||
const [fileError, setFileError] = useState<string | null>(null);
|
const [fileError, setFileError] = useState<string | null>(null);
|
||||||
type FileWithPreview = File & { preview: string };
|
type FileWithPreview = File & { preview: string };
|
||||||
|
|
||||||
|
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
|
||||||
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", label: "SEMUA" },
|
{ id: "all", label: "SEMUA" },
|
||||||
{ id: "5", label: "UMUM" },
|
{ id: "5", label: "UMUM" },
|
||||||
|
|
@ -417,7 +422,8 @@ export default function FormAudio() {
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
setArticleBody(cleanArticleBody || "");
|
setValue("description", cleanArticleBody || "");
|
||||||
|
// setArticleBody(cleanArticleBody || "");
|
||||||
setDetailData(articleData);
|
setDetailData(articleData);
|
||||||
setSelectedArticleId(id);
|
setSelectedArticleId(id);
|
||||||
setArticleImages(articleImagesData || []);
|
setArticleImages(articleImagesData || []);
|
||||||
|
|
@ -808,7 +814,8 @@ export default function FormAudio() {
|
||||||
lang: "id",
|
lang: "id",
|
||||||
contextType: "text",
|
contextType: "text",
|
||||||
urlContext: null,
|
urlContext: null,
|
||||||
context: editorContent,
|
context: getValues("descriptionOri"),
|
||||||
|
// context: editorContent,
|
||||||
createdBy: roleId,
|
createdBy: roleId,
|
||||||
sentiment: "Humorous",
|
sentiment: "Humorous",
|
||||||
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
||||||
|
|
@ -1178,7 +1185,111 @@ export default function FormAudio() {
|
||||||
Select Original Description
|
Select Original Description
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>
|
||||||
|
{t("description", { defaultValue: "Description" })}
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslate(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("descriptionOri"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.error) {
|
||||||
|
const resultText =
|
||||||
|
res?.data?.data?.translations?.[0]?.text ||
|
||||||
|
"";
|
||||||
|
|
||||||
|
setTranslatedContent(resultText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
close();
|
||||||
|
console.error("Translate gagal:", err);
|
||||||
|
} finally {
|
||||||
|
close();
|
||||||
|
setIsLoadingTranslate(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="px-3 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
|
||||||
|
>
|
||||||
|
{isLoadingTranslate
|
||||||
|
? "Translating..."
|
||||||
|
: "Translate to English"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Pilihan bahasa untuk posting */}
|
||||||
|
{roleId === "14" && (
|
||||||
|
<div className="flex items-center gap-4 mb-2">
|
||||||
|
<label className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="id"
|
||||||
|
checked={selectedLang === "id"}
|
||||||
|
onChange={() => setSelectedLang("id")}
|
||||||
|
/>
|
||||||
|
<span>Gunakan Bahasa Indonesia</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Editor Bahasa Indonesia */}
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="descriptionOri"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={onChange}
|
||||||
|
initialData={value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Editor Bahasa Inggris */}
|
||||||
|
{translatedContent && (
|
||||||
|
<div className="mt-4">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<Label className="text-[15px]">
|
||||||
|
English Version
|
||||||
|
</Label>{" "}
|
||||||
|
<label className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="en"
|
||||||
|
checked={selectedLang === "en"}
|
||||||
|
onChange={() => setSelectedLang("en")}
|
||||||
|
disabled={!translatedContent} // kalau belum translate, disable
|
||||||
|
/>
|
||||||
|
<span>Gunakan Bahasa Inggris</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(val: any) => setTranslatedContent(val)}
|
||||||
|
initialData={translatedContent}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{errors.description?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.description.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="py-3 space-y-2">
|
||||||
<Label>
|
<Label>
|
||||||
{t("description", { defaultValue: "Description" })}
|
{t("description", { defaultValue: "Description" })}
|
||||||
</Label>
|
</Label>
|
||||||
|
|
@ -1200,7 +1311,7 @@ export default function FormAudio() {
|
||||||
{errors.description.message}
|
{errors.description.message}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<p className="text-sm font-semibold">Content Rewrite</p>
|
<p className="text-sm font-semibold">Content Rewrite</p>
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ import { useDropzone } from "react-dropzone";
|
||||||
import { Icon } from "@iconify/react";
|
import { Icon } from "@iconify/react";
|
||||||
import { CloudUpload, X } from "lucide-react";
|
import { CloudUpload, X } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { error, loading } from "@/config/swal";
|
import { close, error, loading } from "@/config/swal";
|
||||||
import { Item } from "@radix-ui/react-dropdown-menu";
|
import { Item } from "@radix-ui/react-dropdown-menu";
|
||||||
import { data } from "jquery";
|
import { data } from "jquery";
|
||||||
import { options } from "@fullcalendar/core/preact.js";
|
import { options } from "@fullcalendar/core/preact.js";
|
||||||
|
|
@ -149,6 +149,8 @@ export default function FormImage() {
|
||||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||||
const [filesTemp, setFilesTemp] = useState<File[]>([]);
|
const [filesTemp, setFilesTemp] = useState<File[]>([]);
|
||||||
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
||||||
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", label: "SEMUA" },
|
{ id: "all", label: "SEMUA" },
|
||||||
|
|
@ -449,7 +451,7 @@ export default function FormImage() {
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
setArticleBody(cleanArticleBody || "");
|
setValue("description", cleanArticleBody || "");
|
||||||
setDetailData(articleData);
|
setDetailData(articleData);
|
||||||
setSelectedArticleId(id);
|
setSelectedArticleId(id);
|
||||||
setArticleImages(articleImagesData || []);
|
setArticleImages(articleImagesData || []);
|
||||||
|
|
@ -668,7 +670,6 @@ export default function FormImage() {
|
||||||
|
|
||||||
const resCsrf = await getCsrfToken();
|
const resCsrf = await getCsrfToken();
|
||||||
const csrfToken = resCsrf?.data?.token;
|
const csrfToken = resCsrf?.data?.token;
|
||||||
console.log("CSRF TOKEN : ", csrfToken);
|
|
||||||
const headers = {
|
const headers = {
|
||||||
"X-XSRF-TOKEN": csrfToken,
|
"X-XSRF-TOKEN": csrfToken,
|
||||||
};
|
};
|
||||||
|
|
@ -827,7 +828,7 @@ export default function FormImage() {
|
||||||
lang: "id",
|
lang: "id",
|
||||||
contextType: "text",
|
contextType: "text",
|
||||||
urlContext: null,
|
urlContext: null,
|
||||||
context: editorContent,
|
context: getValues("descriptionOri"),
|
||||||
createdBy: roleId,
|
createdBy: roleId,
|
||||||
sentiment: "Humorous",
|
sentiment: "Humorous",
|
||||||
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
||||||
|
|
@ -1198,9 +1199,9 @@ export default function FormImage() {
|
||||||
className="dark:text-black"
|
className="dark:text-black"
|
||||||
onChange={(value: any) => {
|
onChange={(value: any) => {
|
||||||
onChange(value);
|
onChange(value);
|
||||||
setEditorContent(value);
|
// setEditorContent(value);
|
||||||
}}
|
}}
|
||||||
initialData={articleBody || value}
|
initialData={value}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1239,24 +1240,130 @@ export default function FormImage() {
|
||||||
type="button"
|
type="button"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
try {
|
try {
|
||||||
|
loading();
|
||||||
setIsLoadingTranslate(true);
|
setIsLoadingTranslate(true);
|
||||||
const res = await translateText({
|
const res = await translateText({
|
||||||
text: localContent,
|
text: getValues("descriptionOri"),
|
||||||
sourceLang: "ID",
|
sourceLang: "ID",
|
||||||
targetLang: "EN",
|
targetLang: "EN",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.error && res.data?.translatedText) {
|
if (!res.error) {
|
||||||
setLocalContent(res.data.translatedText);
|
const resultText =
|
||||||
setValue(
|
res?.data?.data?.translations?.[0]?.text ||
|
||||||
"descriptionOri",
|
"";
|
||||||
res.data.translatedText
|
|
||||||
);
|
setTranslatedContent(resultText);
|
||||||
setEditorContent(res.data.translatedText);
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
close();
|
||||||
console.error("Translate gagal:", err);
|
console.error("Translate gagal:", err);
|
||||||
} finally {
|
} finally {
|
||||||
|
close();
|
||||||
|
setIsLoadingTranslate(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="px-3 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
|
||||||
|
>
|
||||||
|
{isLoadingTranslate
|
||||||
|
? "Translating..."
|
||||||
|
: "Translate to English"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Pilihan bahasa untuk posting */}
|
||||||
|
{roleId === "14" && (
|
||||||
|
<div className="flex items-center gap-4 mb-2">
|
||||||
|
<label className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="id"
|
||||||
|
checked={selectedLang === "id"}
|
||||||
|
onChange={() => setSelectedLang("id")}
|
||||||
|
/>
|
||||||
|
<span>Gunakan Bahasa Indonesia</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Editor Bahasa Indonesia */}
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="descriptionOri"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={onChange}
|
||||||
|
initialData={value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Editor Bahasa Inggris */}
|
||||||
|
{translatedContent && (
|
||||||
|
<div className="mt-4">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<Label className="text-[15px]">
|
||||||
|
English Version
|
||||||
|
</Label>{" "}
|
||||||
|
<label className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="en"
|
||||||
|
checked={selectedLang === "en"}
|
||||||
|
onChange={() => setSelectedLang("en")}
|
||||||
|
disabled={!translatedContent} // kalau belum translate, disable
|
||||||
|
/>
|
||||||
|
<span>Gunakan Bahasa Inggris</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(val: any) => setTranslatedContent(val)}
|
||||||
|
initialData={translatedContent}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{errors.description?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.description.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{/* <div className="py-3 space-y-2">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>
|
||||||
|
{t("description", { defaultValue: "Description" })}
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslate(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("descriptionOri"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
console.log("RRRR", res);
|
||||||
|
|
||||||
|
if (!res.error) {
|
||||||
|
// setLocalContent(res.data.translatedText);
|
||||||
|
setValue(
|
||||||
|
"descriptionOri",
|
||||||
|
res?.data?.data?.translations[0]?.text || ""
|
||||||
|
);
|
||||||
|
// setEditorContent(res.data.translatedText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
close();
|
||||||
|
console.error("Translate gagal:", err);
|
||||||
|
} finally {
|
||||||
|
close();
|
||||||
setIsLoadingTranslate(false);
|
setIsLoadingTranslate(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
@ -1269,7 +1376,6 @@ export default function FormImage() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Editor */}
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="descriptionOri"
|
name="descriptionOri"
|
||||||
|
|
@ -1277,10 +1383,10 @@ export default function FormImage() {
|
||||||
<CustomEditor
|
<CustomEditor
|
||||||
onChange={(val: any) => {
|
onChange={(val: any) => {
|
||||||
onChange(val);
|
onChange(val);
|
||||||
setLocalContent(val);
|
// setLocalContent(val);
|
||||||
setEditorContent(val);
|
// setEditorContent(val);
|
||||||
}}
|
}}
|
||||||
initialData={localContent || value}
|
initialData={value}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
@ -1290,7 +1396,7 @@ export default function FormImage() {
|
||||||
{errors.description.message}
|
{errors.description.message}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div> */}
|
||||||
{/* <div className="py-3 space-y-2">
|
{/* <div className="py-3 space-y-2">
|
||||||
<Label>
|
<Label>
|
||||||
{t("description", { defaultValue: "Description" })}
|
{t("description", { defaultValue: "Description" })}
|
||||||
|
|
@ -1314,7 +1420,6 @@ export default function FormImage() {
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
<p className="text-sm font-semibold">Content Rewrite</p>
|
<p className="text-sm font-semibold">Content Rewrite</p>
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -1326,7 +1431,6 @@ export default function FormImage() {
|
||||||
Content Rewrite
|
Content Rewrite
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showRewriteEditor && (
|
{showRewriteEditor && (
|
||||||
<div>
|
<div>
|
||||||
{isGeneratedArticle && (
|
{isGeneratedArticle && (
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,14 @@ import {
|
||||||
getDetailArticle,
|
getDetailArticle,
|
||||||
getGenerateKeywords,
|
getGenerateKeywords,
|
||||||
getGenerateTitle,
|
getGenerateTitle,
|
||||||
|
translateText,
|
||||||
} from "@/service/content/ai";
|
} from "@/service/content/ai";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import { useDropzone } from "react-dropzone";
|
import { useDropzone } from "react-dropzone";
|
||||||
import { Icon } from "@iconify/react";
|
import { Icon } from "@iconify/react";
|
||||||
import { CloudUpload } from "lucide-react";
|
import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { error, loading } from "@/config/swal";
|
import { close, error, loading } from "@/config/swal";
|
||||||
import { Item } from "@radix-ui/react-dropdown-menu";
|
import { Item } from "@radix-ui/react-dropdown-menu";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { getCsrfToken } from "@/service/auth";
|
import { getCsrfToken } from "@/service/auth";
|
||||||
|
|
@ -142,6 +143,11 @@ export default function FormTeks() {
|
||||||
|
|
||||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||||
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
|
||||||
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", label: "SEMUA" },
|
{ id: "all", label: "SEMUA" },
|
||||||
{ id: "5", label: "UMUM" },
|
{ id: "5", label: "UMUM" },
|
||||||
|
|
@ -429,7 +435,8 @@ export default function FormTeks() {
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
setArticleBody(cleanArticleBody || "");
|
setValue("description", cleanArticleBody || "");
|
||||||
|
// setArticleBody(cleanArticleBody || "");
|
||||||
setDetailData(articleData);
|
setDetailData(articleData);
|
||||||
setSelectedArticleId(id);
|
setSelectedArticleId(id);
|
||||||
setArticleImages(articleImagesData || []);
|
setArticleImages(articleImagesData || []);
|
||||||
|
|
@ -819,7 +826,8 @@ export default function FormTeks() {
|
||||||
lang: "id",
|
lang: "id",
|
||||||
contextType: "text",
|
contextType: "text",
|
||||||
urlContext: null,
|
urlContext: null,
|
||||||
context: editorContent,
|
context: getValues("descriptionOri"),
|
||||||
|
// context: editorContent,
|
||||||
createdBy: roleId,
|
createdBy: roleId,
|
||||||
sentiment: "Humorous",
|
sentiment: "Humorous",
|
||||||
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
||||||
|
|
@ -1185,7 +1193,110 @@ export default function FormTeks() {
|
||||||
Select Original Description
|
Select Original Description
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>
|
||||||
|
{t("description", { defaultValue: "Description" })}
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslate(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("descriptionOri"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.error) {
|
||||||
|
const resultText =
|
||||||
|
res?.data?.data?.translations?.[0]?.text ||
|
||||||
|
"";
|
||||||
|
|
||||||
|
setTranslatedContent(resultText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
close();
|
||||||
|
console.error("Translate gagal:", err);
|
||||||
|
} finally {
|
||||||
|
close();
|
||||||
|
setIsLoadingTranslate(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="px-3 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
|
||||||
|
>
|
||||||
|
{isLoadingTranslate
|
||||||
|
? "Translating..."
|
||||||
|
: "Translate to English"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Pilihan bahasa untuk posting */}
|
||||||
|
{roleId === "14" && (
|
||||||
|
<div className="flex items-center gap-4 mb-2">
|
||||||
|
<label className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="id"
|
||||||
|
checked={selectedLang === "id"}
|
||||||
|
onChange={() => setSelectedLang("id")}
|
||||||
|
/>
|
||||||
|
<span>Gunakan Bahasa Indonesia</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Editor Bahasa Indonesia */}
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="descriptionOri"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={onChange}
|
||||||
|
initialData={value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Editor Bahasa Inggris */}
|
||||||
|
{translatedContent && (
|
||||||
|
<div className="mt-4">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<Label className="text-[15px]">
|
||||||
|
English Version
|
||||||
|
</Label>{" "}
|
||||||
|
<label className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="en"
|
||||||
|
checked={selectedLang === "en"}
|
||||||
|
onChange={() => setSelectedLang("en")}
|
||||||
|
disabled={!translatedContent} // kalau belum translate, disable
|
||||||
|
/>
|
||||||
|
<span>Gunakan Bahasa Inggris</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(val: any) => setTranslatedContent(val)}
|
||||||
|
initialData={translatedContent}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{errors.description?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.description.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{/* <div className="py-3 space-y-2">
|
||||||
<Label>
|
<Label>
|
||||||
{t("description", { defaultValue: "Description" })}
|
{t("description", { defaultValue: "Description" })}
|
||||||
</Label>
|
</Label>
|
||||||
|
|
@ -1207,7 +1318,7 @@ export default function FormTeks() {
|
||||||
{errors.description.message}
|
{errors.description.message}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<p className="text-sm font-semibold">Content Rewrite</p>
|
<p className="text-sm font-semibold">Content Rewrite</p>
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
|
|
@ -1329,8 +1440,6 @@ export default function FormTeks() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Submit Button */}
|
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
<div className="w-full lg:w-4/12">
|
<div className="w-full lg:w-4/12">
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,14 @@ import {
|
||||||
getDetailArticle,
|
getDetailArticle,
|
||||||
getGenerateKeywords,
|
getGenerateKeywords,
|
||||||
getGenerateTitle,
|
getGenerateTitle,
|
||||||
|
translateText,
|
||||||
} from "@/service/content/ai";
|
} from "@/service/content/ai";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import { useDropzone } from "react-dropzone";
|
import { useDropzone } from "react-dropzone";
|
||||||
import { Icon } from "@iconify/react";
|
import { Icon } from "@iconify/react";
|
||||||
import { CloudUpload } from "lucide-react";
|
import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { error, loading } from "@/config/swal";
|
import { close, error, loading } from "@/config/swal";
|
||||||
import { Item } from "@radix-ui/react-dropdown-menu";
|
import { Item } from "@radix-ui/react-dropdown-menu";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { getCsrfToken } from "@/service/auth";
|
import { getCsrfToken } from "@/service/auth";
|
||||||
|
|
@ -146,6 +147,10 @@ export default function FormVideo() {
|
||||||
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
||||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||||
|
|
||||||
|
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
|
||||||
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", label: "SEMUA" },
|
{ id: "all", label: "SEMUA" },
|
||||||
{ id: "5", label: "UMUM" },
|
{ id: "5", label: "UMUM" },
|
||||||
|
|
@ -423,7 +428,8 @@ export default function FormVideo() {
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
const articleImagesData = articleData?.imagesUrl?.split(",");
|
const articleImagesData = articleData?.imagesUrl?.split(",");
|
||||||
setArticleBody(cleanArticleBody || "");
|
setValue("description", cleanArticleBody || "");
|
||||||
|
// setArticleBody(cleanArticleBody || "");
|
||||||
setDetailData(articleData);
|
setDetailData(articleData);
|
||||||
setSelectedArticleId(id);
|
setSelectedArticleId(id);
|
||||||
setArticleImages(articleImagesData || []);
|
setArticleImages(articleImagesData || []);
|
||||||
|
|
@ -827,7 +833,8 @@ export default function FormVideo() {
|
||||||
lang: "id",
|
lang: "id",
|
||||||
contextType: "text",
|
contextType: "text",
|
||||||
urlContext: null,
|
urlContext: null,
|
||||||
context: editorContent, // Ambil isi editor original
|
context: getValues("descriptionOri"),
|
||||||
|
// context: editorContent,
|
||||||
createdBy: roleId,
|
createdBy: roleId,
|
||||||
sentiment: "Humorous",
|
sentiment: "Humorous",
|
||||||
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
||||||
|
|
@ -1193,7 +1200,109 @@ export default function FormVideo() {
|
||||||
Select Original Description
|
Select Original Description
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>
|
||||||
|
{t("description", { defaultValue: "Description" })}
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslate(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("descriptionOri"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.error) {
|
||||||
|
const resultText =
|
||||||
|
res?.data?.data?.translations?.[0]?.text ||
|
||||||
|
"";
|
||||||
|
|
||||||
|
setTranslatedContent(resultText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
close();
|
||||||
|
console.error("Translate gagal:", err);
|
||||||
|
} finally {
|
||||||
|
close();
|
||||||
|
setIsLoadingTranslate(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="px-3 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
|
||||||
|
>
|
||||||
|
{isLoadingTranslate
|
||||||
|
? "Translating..."
|
||||||
|
: "Translate to English"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Pilihan bahasa untuk posting */}
|
||||||
|
<div className="flex items-center gap-4 mb-2">
|
||||||
|
<label className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="id"
|
||||||
|
checked={selectedLang === "id"}
|
||||||
|
onChange={() => setSelectedLang("id")}
|
||||||
|
/>
|
||||||
|
<span>Gunakan Bahasa Indonesia</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Editor Bahasa Indonesia */}
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="descriptionOri"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={onChange}
|
||||||
|
initialData={value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Editor Bahasa Inggris */}
|
||||||
|
{translatedContent && (
|
||||||
|
<div className="mt-4">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<Label className="text-[15px]">
|
||||||
|
English Version
|
||||||
|
</Label>{" "}
|
||||||
|
<label className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
value="en"
|
||||||
|
checked={selectedLang === "en"}
|
||||||
|
onChange={() => setSelectedLang("en")}
|
||||||
|
disabled={!translatedContent} // kalau belum translate, disable
|
||||||
|
/>
|
||||||
|
<span>Gunakan Bahasa Inggris</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(val: any) => setTranslatedContent(val)}
|
||||||
|
initialData={translatedContent}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{errors.description?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.description.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="py-3 space-y-2">
|
||||||
<Label>
|
<Label>
|
||||||
{t("description", { defaultValue: "Description" })}
|
{t("description", { defaultValue: "Description" })}
|
||||||
</Label>
|
</Label>
|
||||||
|
|
@ -1215,7 +1324,7 @@ export default function FormVideo() {
|
||||||
{errors.description.message}
|
{errors.description.message}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<p className="text-sm font-semibold">Content Rewrite</p>
|
<p className="text-sm font-semibold">Content Rewrite</p>
|
||||||
<div className="my-2">
|
<div className="my-2">
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ export async function getTagsBySubCategoryId(subCategory: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function listEnableCategory(type: any) {
|
export async function listEnableCategory(type: any) {
|
||||||
const url = `media/categories/list?enablePage=0&sort=desc&sortBy=id&type=${type}`;
|
const url = `media/categories/list?enablePage=0&sort=desc&sortBy=id&type=${type}&isInt=true`;
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue