Merge branch 'main' of https://gitlab.com/hanifsalafi/mediahub_redesign into prod
This commit is contained in:
commit
4f28de0a12
|
|
@ -145,10 +145,10 @@ export default function FormAudio() {
|
||||||
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
||||||
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 [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
|
||||||
const [translatedContent, setTranslatedContent] = React.useState("");
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
|
const [translatedTitle, setTranslatedTitle] = useState("");
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", label: "SEMUA" },
|
{ id: "all", label: "SEMUA" },
|
||||||
|
|
@ -618,29 +618,49 @@ export default function FormAudio() {
|
||||||
const save = async (data: AudioSchema) => {
|
const save = async (data: AudioSchema) => {
|
||||||
loading();
|
loading();
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
const finalTitle = isSwitchOn ? title : data.title;
|
// const finalTitle = isSwitchOn ? title : data.title;
|
||||||
|
|
||||||
// pilih description dasar
|
// // pilih description dasar
|
||||||
let finalDescription = isSwitchOn
|
// let finalDescription = isSwitchOn
|
||||||
? data.description
|
// ? data.description
|
||||||
: selectedFileType === "rewrite"
|
// : selectedFileType === "rewrite"
|
||||||
? data.rewriteDescription
|
// ? data.rewriteDescription
|
||||||
: data.descriptionOri;
|
// : data.descriptionOri;
|
||||||
|
|
||||||
|
const finalTitle =
|
||||||
|
translatedTitle && translatedTitle.trim() !== ""
|
||||||
|
? translatedTitle
|
||||||
|
: isSwitchOn
|
||||||
|
? title
|
||||||
|
: data.title;
|
||||||
|
|
||||||
|
const finalDescription =
|
||||||
|
translatedContent && translatedContent.trim() !== ""
|
||||||
|
? translatedContent
|
||||||
|
: isSwitchOn
|
||||||
|
? data.description
|
||||||
|
: selectedFileType === "rewrite"
|
||||||
|
? data.rewriteDescription
|
||||||
|
: data.descriptionOri;
|
||||||
|
|
||||||
|
if (!finalDescription?.trim()) {
|
||||||
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 👉 tempelkan hasil translate ke field form & pakai sebagai description
|
// 👉 tempelkan hasil translate ke field form & pakai sebagai description
|
||||||
if (translatedContent) {
|
if (translatedContent) {
|
||||||
data.descriptionOri = translatedContent; // update ke form
|
data.descriptionOri = translatedContent;
|
||||||
finalDescription = translatedContent; // pakai untuk request
|
|
||||||
console.log(
|
console.log(
|
||||||
"🌍 Translate dimasukkan ke descriptionOri:",
|
"🌍 Translate dimasukkan ke descriptionOri:",
|
||||||
translatedContent
|
translatedContent
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!finalDescription?.trim()) {
|
// if (!finalDescription?.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
// MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
let requestData: {
|
let requestData: {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -963,7 +983,44 @@ export default function FormAudio() {
|
||||||
<div className="gap-5 mb-5">
|
<div className="gap-5 mb-5">
|
||||||
{/* Input Title */}
|
{/* Input Title */}
|
||||||
<div className="space-y-2 py-3">
|
<div className="space-y-2 py-3">
|
||||||
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslate(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("title"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
if (!res.error) {
|
||||||
|
const resultText =
|
||||||
|
res?.data?.data?.translations?.[0]?.text || "";
|
||||||
|
setTranslatedTitle(resultText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
close();
|
||||||
|
console.error("Translate title 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 Title"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Title Bahasa Indonesia */}
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="title"
|
name="title"
|
||||||
|
|
@ -973,10 +1030,27 @@ export default function FormAudio() {
|
||||||
type="text"
|
type="text"
|
||||||
value={field.value}
|
value={field.value}
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
placeholder="Enter Title"
|
placeholder="Masukkan Judul Bahasa Indonesia"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Versi English (muncul setelah translate) */}
|
||||||
|
{translatedTitle && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Label className="text-sm font-semibold">
|
||||||
|
English Title
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={translatedTitle}
|
||||||
|
onChange={(e) => setTranslatedTitle(e.target.value)}
|
||||||
|
placeholder="Translated Title"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{errors.title?.message && (
|
{errors.title?.message && (
|
||||||
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,6 @@ import {
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
|
||||||
|
|
||||||
import { register } from "module";
|
|
||||||
import { Switch } from "@/components/ui/switch";
|
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import {
|
import {
|
||||||
createMedia,
|
createMedia,
|
||||||
|
|
@ -197,11 +193,11 @@ export default function FormAudioUpdate() {
|
||||||
useState(false);
|
useState(false);
|
||||||
const [mainCheckboxChangeType, setMainCheckboxChangeType] =
|
const [mainCheckboxChangeType, setMainCheckboxChangeType] =
|
||||||
useState<string>("");
|
useState<string>("");
|
||||||
|
|
||||||
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
|
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
|
||||||
const [translatedContent, setTranslatedContent] = React.useState("");
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
const roleId = getCookiesDecrypt("urie");
|
const roleId = getCookiesDecrypt("urie");
|
||||||
|
const [translatedTitle, setTranslatedTitle] = useState("");
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", name: "SEMUA" },
|
{ id: "all", name: "SEMUA" },
|
||||||
|
|
@ -1224,15 +1220,18 @@ export default function FormAudioUpdate() {
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
|
|
||||||
// ✅ tentukan isi description sesuai pilihan bahasa
|
// ✅ tentukan isi description sesuai pilihan bahasa
|
||||||
const descFinal =
|
// const descFinal =
|
||||||
selectedLang === "en" && translatedContent
|
// selectedLang === "en" && translatedContent
|
||||||
? translatedContent
|
// ? translatedContent
|
||||||
: data.description;
|
// : data.description;
|
||||||
|
|
||||||
|
const descFinal = translatedContent || data.description;
|
||||||
|
const finalTitle = translatedTitle || data.title;
|
||||||
|
|
||||||
const requestData = {
|
const requestData = {
|
||||||
...data,
|
...data,
|
||||||
id: detail?.id,
|
id: detail?.id,
|
||||||
title: data.title,
|
title: finalTitle,
|
||||||
description: htmlToString(descFinal),
|
description: htmlToString(descFinal),
|
||||||
htmlDescription: descFinal,
|
htmlDescription: descFinal,
|
||||||
fileTypeId,
|
fileTypeId,
|
||||||
|
|
@ -1534,7 +1533,43 @@ export default function FormAudioUpdate() {
|
||||||
<div className="gap-5 mb-5">
|
<div className="gap-5 mb-5">
|
||||||
{/* Input Title */}
|
{/* Input Title */}
|
||||||
<div className="space-y-2 py-3">
|
<div className="space-y-2 py-3">
|
||||||
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslate(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("title"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
if (!res.error) {
|
||||||
|
const resultText =
|
||||||
|
res?.data?.data?.translations?.[0]?.text || "";
|
||||||
|
setTranslatedTitle(resultText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
close();
|
||||||
|
console.error("Translate title 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 Title"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="title"
|
name="title"
|
||||||
|
|
@ -1542,18 +1577,36 @@ export default function FormAudioUpdate() {
|
||||||
<Input
|
<Input
|
||||||
size="md"
|
size="md"
|
||||||
type="text"
|
type="text"
|
||||||
value={field?.value}
|
value={field.value}
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
placeholder="Enter Title"
|
placeholder="Enter Title"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* English translated title appears below when available */}
|
||||||
|
{translatedTitle && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Label className="text-sm font-semibold">
|
||||||
|
English Version
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={translatedTitle}
|
||||||
|
onChange={(e) => setTranslatedTitle(e.target.value)}
|
||||||
|
placeholder="Translated Title"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{errors.title?.message && (
|
{errors.title?.message && (
|
||||||
<p className="text-red-400 text-sm">
|
<p className="text-red-400 text-sm">
|
||||||
{errors.title.message}
|
{errors.title.message}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="py-3 w-full space-y-2">
|
<div className="py-3 w-full space-y-2">
|
||||||
<Label>{t("category", { defaultValue: "Category" })}</Label>
|
<Label>{t("category", { defaultValue: "Category" })}</Label>
|
||||||
|
|
@ -1617,7 +1670,7 @@ export default function FormAudioUpdate() {
|
||||||
if (!res.error) {
|
if (!res.error) {
|
||||||
const resultText =
|
const resultText =
|
||||||
res?.data?.data?.translations?.[0]?.text || "";
|
res?.data?.data?.translations?.[0]?.text || "";
|
||||||
|
// Overwrite data.description but still show both
|
||||||
setTranslatedContent(resultText);
|
setTranslatedContent(resultText);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -1632,55 +1685,34 @@ export default function FormAudioUpdate() {
|
||||||
>
|
>
|
||||||
{isLoadingTranslate
|
{isLoadingTranslate
|
||||||
? "Translating..."
|
? "Translating..."
|
||||||
: "Translate to English"}
|
: "Translate Description"}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</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 */}
|
{/* Editor Bahasa Indonesia */}
|
||||||
<Controller
|
<div className="mt-3">
|
||||||
control={control}
|
<Label className="text-sm font-semibold">
|
||||||
name="description"
|
Indonesian Version
|
||||||
render={({ field }) => (
|
</Label>
|
||||||
<CustomEditor
|
<Controller
|
||||||
onChange={field.onChange}
|
control={control}
|
||||||
initialData={field.value}
|
name="description"
|
||||||
/>
|
render={({ field }) => (
|
||||||
)}
|
<CustomEditor
|
||||||
/>
|
onChange={field.onChange}
|
||||||
|
initialData={field.value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Editor Bahasa Inggris */}
|
{/* English translated version muncul setelah translate */}
|
||||||
{translatedContent && (
|
{translatedContent && (
|
||||||
<div className="mt-4">
|
<div className="mt-5">
|
||||||
<div className="flex flex-col">
|
<Label className="text-sm font-semibold">
|
||||||
<Label className="text-[15px]">English Version</Label>
|
English Version
|
||||||
<label className="flex items-center gap-2">
|
</Label>
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
value="en"
|
|
||||||
checked={selectedLang === "en"}
|
|
||||||
onChange={() => setSelectedLang("en")}
|
|
||||||
disabled={!translatedContent}
|
|
||||||
/>
|
|
||||||
<span>Gunakan Bahasa Inggris</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CustomEditor
|
<CustomEditor
|
||||||
onChange={(val: any) => setTranslatedContent(val)}
|
onChange={(val: any) => setTranslatedContent(val)}
|
||||||
initialData={translatedContent}
|
initialData={translatedContent}
|
||||||
|
|
|
||||||
|
|
@ -1353,7 +1353,6 @@ export default function FormImage() {
|
||||||
value={selectedFileType}
|
value={selectedFileType}
|
||||||
className="grid-cols-1"
|
className="grid-cols-1"
|
||||||
>
|
>
|
||||||
{/* HAPUS radio, ganti jadi preview side-by-side */}
|
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<Label className="text-[15px]">
|
<Label className="text-[15px]">
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,6 @@ import {
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||||
|
|
||||||
import { register } from "module";
|
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import {
|
import {
|
||||||
|
|
@ -140,13 +138,12 @@ export default function FormTeks() {
|
||||||
let uploadPersen = 0;
|
let uploadPersen = 0;
|
||||||
const [isStartUpload, setIsStartUpload] = useState(false);
|
const [isStartUpload, setIsStartUpload] = useState(false);
|
||||||
const [counterProgress, setCounterProgress] = useState(0);
|
const [counterProgress, setCounterProgress] = useState(0);
|
||||||
|
|
||||||
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 [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
|
||||||
const [translatedContent, setTranslatedContent] = React.useState("");
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
|
const [translatedTitle, setTranslatedTitle] = useState("");
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", label: "SEMUA" },
|
{ id: "all", label: "SEMUA" },
|
||||||
|
|
@ -647,13 +644,34 @@ export default function FormTeks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
const finalTitle = isSwitchOn ? title : data.title;
|
// const finalTitle = isSwitchOn ? title : data.title;
|
||||||
// const finalDescription = articleBody || data.description;
|
// const finalDescription = articleBody || data.description;
|
||||||
const finalDescription = isSwitchOn
|
// const finalDescription = isSwitchOn
|
||||||
? data.description
|
// ? data.description
|
||||||
: selectedFileType === "rewrite"
|
// : selectedFileType === "rewrite"
|
||||||
? data.rewriteDescription
|
// ? data.rewriteDescription
|
||||||
: data.descriptionOri;
|
// : data.descriptionOri;
|
||||||
|
|
||||||
|
// if (!finalDescription?.trim()) {
|
||||||
|
// MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
const finalTitle =
|
||||||
|
translatedTitle && translatedTitle.trim() !== ""
|
||||||
|
? translatedTitle
|
||||||
|
: isSwitchOn
|
||||||
|
? title
|
||||||
|
: data.title;
|
||||||
|
|
||||||
|
const finalDescription =
|
||||||
|
translatedContent && translatedContent.trim() !== ""
|
||||||
|
? translatedContent
|
||||||
|
: isSwitchOn
|
||||||
|
? data.description
|
||||||
|
: selectedFileType === "rewrite"
|
||||||
|
? data.rewriteDescription
|
||||||
|
: data.descriptionOri;
|
||||||
|
|
||||||
if (!finalDescription?.trim()) {
|
if (!finalDescription?.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
|
|
@ -974,6 +992,80 @@ export default function FormTeks() {
|
||||||
<div className="gap-5 mb-5">
|
<div className="gap-5 mb-5">
|
||||||
{/* Input Title */}
|
{/* Input Title */}
|
||||||
<div className="space-y-2 py-3">
|
<div className="space-y-2 py-3">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslate(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("title"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
if (!res.error) {
|
||||||
|
const resultText =
|
||||||
|
res?.data?.data?.translations?.[0]?.text || "";
|
||||||
|
setTranslatedTitle(resultText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
close();
|
||||||
|
console.error("Translate title 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 Title"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Title Bahasa Indonesia */}
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="title"
|
||||||
|
render={({ field }) => (
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
placeholder="Masukkan Judul Bahasa Indonesia"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Versi English (muncul setelah translate) */}
|
||||||
|
{translatedTitle && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Label className="text-sm font-semibold">
|
||||||
|
English Title
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={translatedTitle}
|
||||||
|
onChange={(e) => setTranslatedTitle(e.target.value)}
|
||||||
|
placeholder="Translated Title"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{errors.title?.message && (
|
||||||
|
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="space-y-2 py-3">
|
||||||
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -991,7 +1083,7 @@ export default function FormTeks() {
|
||||||
{errors.title?.message && (
|
{errors.title?.message && (
|
||||||
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="py-3 w-full space-y-2">
|
<div className="py-3 w-full space-y-2">
|
||||||
|
|
@ -1317,12 +1409,10 @@ export default function FormTeks() {
|
||||||
sourceLang: "ID",
|
sourceLang: "ID",
|
||||||
targetLang: "EN",
|
targetLang: "EN",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.error) {
|
if (!res.error) {
|
||||||
const resultText =
|
const resultText =
|
||||||
res?.data?.data?.translations?.[0]?.text ||
|
res?.data?.data?.translations?.[0]?.text ||
|
||||||
"";
|
"";
|
||||||
|
|
||||||
setTranslatedContent(resultText);
|
setTranslatedContent(resultText);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -1337,57 +1427,34 @@ export default function FormTeks() {
|
||||||
>
|
>
|
||||||
{isLoadingTranslate
|
{isLoadingTranslate
|
||||||
? "Translating..."
|
? "Translating..."
|
||||||
: "Translate to English"}
|
: "Translate Description"}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Pilihan bahasa untuk posting */}
|
{/* Deskripsi Bahasa Indonesia */}
|
||||||
{roleId === "14" && (
|
<div className="mt-2">
|
||||||
<div className="flex items-center gap-4 mb-2">
|
<Label className="text-sm font-semibold">
|
||||||
<label className="flex items-center gap-2">
|
Indonesian Version
|
||||||
<input
|
</Label>
|
||||||
type="radio"
|
<Controller
|
||||||
value="id"
|
control={control}
|
||||||
checked={selectedLang === "id"}
|
name="descriptionOri"
|
||||||
onChange={() => setSelectedLang("id")}
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={onChange}
|
||||||
|
initialData={value}
|
||||||
/>
|
/>
|
||||||
<span>Gunakan Bahasa Indonesia</span>
|
)}
|
||||||
</label>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Editor Bahasa Indonesia */}
|
{/* Versi Inggris muncul setelah translate */}
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name="descriptionOri"
|
|
||||||
render={({ field: { onChange, value } }) => (
|
|
||||||
<CustomEditor
|
|
||||||
onChange={onChange}
|
|
||||||
initialData={value}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Editor Bahasa Inggris */}
|
|
||||||
{translatedContent && (
|
{translatedContent && (
|
||||||
<div className="mt-4">
|
<div className="mt-5">
|
||||||
<div className="flex flex-col">
|
<Label className="text-sm font-semibold">
|
||||||
<Label className="text-[15px]">
|
English Version
|
||||||
English Version
|
</Label>
|
||||||
</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
|
<CustomEditor
|
||||||
onChange={(val: any) => setTranslatedContent(val)}
|
onChange={(val: any) => setTranslatedContent(val)}
|
||||||
initialData={translatedContent}
|
initialData={translatedContent}
|
||||||
|
|
@ -1401,6 +1468,7 @@ export default function FormTeks() {
|
||||||
</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" })}
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,7 @@ export default function FormTeksUpdate() {
|
||||||
const [translatedContent, setTranslatedContent] = React.useState("");
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
const roleId = getCookiesDecrypt("urie");
|
const roleId = getCookiesDecrypt("urie");
|
||||||
|
const [translatedTitle, setTranslatedTitle] = useState("");
|
||||||
|
|
||||||
let fileTypeId = "3";
|
let fileTypeId = "3";
|
||||||
const isDetailOfRegionShowed = false;
|
const isDetailOfRegionShowed = false;
|
||||||
|
|
@ -1251,18 +1252,18 @@ export default function FormTeksUpdate() {
|
||||||
loading();
|
loading();
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
|
|
||||||
// ✅ tentukan isi description sesuai pilihan bahasa
|
// const descFinal =
|
||||||
const descFinal =
|
// selectedLang === "en" && translatedContent
|
||||||
selectedLang === "en" && translatedContent
|
// ? translatedContent
|
||||||
? translatedContent
|
// : data.description;
|
||||||
: data.description;
|
const descFinal = translatedContent || data.description;
|
||||||
|
const finalTitle = translatedTitle || data.title;
|
||||||
const requestData = {
|
const requestData = {
|
||||||
...data,
|
...data,
|
||||||
id: detail?.id,
|
id: detail?.id,
|
||||||
title: data.title,
|
title: finalTitle,
|
||||||
description: htmlToString(descFinal), // plain text
|
description: htmlToString(descFinal),
|
||||||
htmlDescription: descFinal, // HTML (dipakai di editor/preview)
|
htmlDescription: descFinal,
|
||||||
fileTypeId,
|
fileTypeId,
|
||||||
categoryId: selectedTarget,
|
categoryId: selectedTarget,
|
||||||
subCategoryId: selectedTarget,
|
subCategoryId: selectedTarget,
|
||||||
|
|
@ -1532,6 +1533,81 @@ export default function FormTeksUpdate() {
|
||||||
<div className="gap-5 mb-5">
|
<div className="gap-5 mb-5">
|
||||||
{/* Input Title */}
|
{/* Input Title */}
|
||||||
<div className="space-y-2 py-3">
|
<div className="space-y-2 py-3">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslate(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("title"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
if (!res.error) {
|
||||||
|
const resultText =
|
||||||
|
res?.data?.data?.translations?.[0]?.text || "";
|
||||||
|
setTranslatedTitle(resultText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
close();
|
||||||
|
console.error("Translate title 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 Title"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="title"
|
||||||
|
render={({ field }) => (
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
placeholder="Enter Title"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* English translated title appears below when available */}
|
||||||
|
{translatedTitle && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Label className="text-sm font-semibold">
|
||||||
|
English Version
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={translatedTitle}
|
||||||
|
onChange={(e) => setTranslatedTitle(e.target.value)}
|
||||||
|
placeholder="Translated Title"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{errors.title?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.title.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="space-y-2 py-3">
|
||||||
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -1551,7 +1627,7 @@ export default function FormTeksUpdate() {
|
||||||
{errors.title.message}
|
{errors.title.message}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div> */}
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="py-3 w-full space-y-2">
|
<div className="py-3 w-full space-y-2">
|
||||||
<Label>{t("category", { defaultValue: "Category" })}</Label>
|
<Label>{t("category", { defaultValue: "Category" })}</Label>
|
||||||
|
|
@ -1592,7 +1668,6 @@ export default function FormTeksUpdate() {
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<Label>
|
<Label>
|
||||||
|
|
@ -1615,7 +1690,7 @@ export default function FormTeksUpdate() {
|
||||||
if (!res.error) {
|
if (!res.error) {
|
||||||
const resultText =
|
const resultText =
|
||||||
res?.data?.data?.translations?.[0]?.text || "";
|
res?.data?.data?.translations?.[0]?.text || "";
|
||||||
|
// Overwrite data.description but still show both
|
||||||
setTranslatedContent(resultText);
|
setTranslatedContent(resultText);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -1630,55 +1705,34 @@ export default function FormTeksUpdate() {
|
||||||
>
|
>
|
||||||
{isLoadingTranslate
|
{isLoadingTranslate
|
||||||
? "Translating..."
|
? "Translating..."
|
||||||
: "Translate to English"}
|
: "Translate Description"}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</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 */}
|
{/* Editor Bahasa Indonesia */}
|
||||||
<Controller
|
<div className="mt-3">
|
||||||
control={control}
|
<Label className="text-sm font-semibold">
|
||||||
name="description"
|
Indonesian Version
|
||||||
render={({ field }) => (
|
</Label>
|
||||||
<CustomEditor
|
<Controller
|
||||||
onChange={field.onChange}
|
control={control}
|
||||||
initialData={field.value}
|
name="description"
|
||||||
/>
|
render={({ field }) => (
|
||||||
)}
|
<CustomEditor
|
||||||
/>
|
onChange={field.onChange}
|
||||||
|
initialData={field.value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Editor Bahasa Inggris */}
|
{/* English translated version muncul setelah translate */}
|
||||||
{translatedContent && (
|
{translatedContent && (
|
||||||
<div className="mt-4">
|
<div className="mt-5">
|
||||||
<div className="flex flex-col">
|
<Label className="text-sm font-semibold">
|
||||||
<Label className="text-[15px]">English Version</Label>
|
English Version
|
||||||
<label className="flex items-center gap-2">
|
</Label>
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
value="en"
|
|
||||||
checked={selectedLang === "en"}
|
|
||||||
onChange={() => setSelectedLang("en")}
|
|
||||||
disabled={!translatedContent}
|
|
||||||
/>
|
|
||||||
<span>Gunakan Bahasa Inggris</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CustomEditor
|
<CustomEditor
|
||||||
onChange={(val: any) => setTranslatedContent(val)}
|
onChange={(val: any) => setTranslatedContent(val)}
|
||||||
initialData={translatedContent}
|
initialData={translatedContent}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,6 @@ import {
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||||
|
|
||||||
import { register } from "module";
|
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import {
|
import {
|
||||||
|
|
@ -36,7 +34,6 @@ import {
|
||||||
listEnableCategory,
|
listEnableCategory,
|
||||||
uploadThumbnail,
|
uploadThumbnail,
|
||||||
} from "@/service/content/content";
|
} from "@/service/content/content";
|
||||||
import { uploadThumbnailBlog } from "@/service/blog/blog";
|
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import {
|
import {
|
||||||
generateDataArticle,
|
generateDataArticle,
|
||||||
|
|
@ -52,10 +49,8 @@ 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 { close, error, loading } from "@/config/swal";
|
import { close, error, loading } from "@/config/swal";
|
||||||
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";
|
||||||
import { Link } from "@/i18n/routing";
|
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { htmlToString } from "@/utils/globals";
|
import { htmlToString } from "@/utils/globals";
|
||||||
|
|
||||||
|
|
@ -146,10 +141,12 @@ export default function FormVideo() {
|
||||||
const [counterProgress, setCounterProgress] = useState(0);
|
const [counterProgress, setCounterProgress] = useState(0);
|
||||||
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 [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
|
||||||
const [translatedContent, setTranslatedContent] = React.useState("");
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
|
// 🔹 State untuk translate Title
|
||||||
|
const [translatedTitle, setTranslatedTitle] = useState("");
|
||||||
|
const [isLoadingTranslateTitle, setIsLoadingTranslateTitle] = useState(false);
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", label: "SEMUA" },
|
{ id: "all", label: "SEMUA" },
|
||||||
|
|
@ -536,27 +533,54 @@ export default function FormVideo() {
|
||||||
}
|
}
|
||||||
loading();
|
loading();
|
||||||
const finalTags = data.tags.join(", ");
|
const finalTags = data.tags.join(", ");
|
||||||
const finalTitle = isSwitchOn ? title : data.title;
|
// const finalTitle = isSwitchOn ? title : data.title;
|
||||||
// const finalDescription = articleBody || data.description;
|
// const finalDescription = articleBody || data.description;
|
||||||
const finalDescription = isSwitchOn
|
// const finalDescription = isSwitchOn
|
||||||
? data.description
|
// ? data.description
|
||||||
: selectedFileType === "rewrite"
|
// : selectedFileType === "rewrite"
|
||||||
? data.rewriteDescription
|
// ? data.rewriteDescription
|
||||||
: data.descriptionOri;
|
// : data.descriptionOri;
|
||||||
|
|
||||||
|
// if (!finalDescription?.trim()) {
|
||||||
|
// MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 👉 tempelkan hasil translate ke form agar ikut terkirim
|
||||||
|
// if (translatedContent) {
|
||||||
|
// data.descriptionOri = translatedContent;
|
||||||
|
// console.log(
|
||||||
|
// "🌍 Translate dimasukkan ke descriptionOri:",
|
||||||
|
// translatedContent
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Tentukan title final (gunakan versi translate kalau ada)
|
||||||
|
const finalTitle =
|
||||||
|
translatedTitle && translatedTitle.trim() !== ""
|
||||||
|
? translatedTitle
|
||||||
|
: isSwitchOn
|
||||||
|
? title
|
||||||
|
: data.title;
|
||||||
|
|
||||||
|
// Tentukan deskripsi final:
|
||||||
|
// Jika ada hasil translate, kirim itu ke backend
|
||||||
|
const finalDescription =
|
||||||
|
translatedContent && translatedContent.trim() !== ""
|
||||||
|
? translatedContent
|
||||||
|
: isSwitchOn
|
||||||
|
? data.description
|
||||||
|
: selectedFileType === "rewrite"
|
||||||
|
? data.rewriteDescription
|
||||||
|
: data.descriptionOri;
|
||||||
|
|
||||||
if (!finalDescription?.trim()) {
|
if (!finalDescription?.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 👉 tempelkan hasil translate ke form agar ikut terkirim
|
console.log("📝 Deskripsi final yang dikirim:", finalDescription);
|
||||||
if (translatedContent) {
|
|
||||||
data.descriptionOri = translatedContent;
|
|
||||||
console.log(
|
|
||||||
"🌍 Translate dimasukkan ke descriptionOri:",
|
|
||||||
translatedContent
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let requestData: {
|
let requestData: {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -883,7 +907,81 @@ export default function FormVideo() {
|
||||||
{t("form-video", { defaultValue: "Form Video" })}
|
{t("form-video", { defaultValue: "Form Video" })}
|
||||||
</p>
|
</p>
|
||||||
<div className="gap-5 mb-5">
|
<div className="gap-5 mb-5">
|
||||||
|
{/* Input Title dengan tombol translate */}
|
||||||
<div className="space-y-2 py-3">
|
<div className="space-y-2 py-3">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslateTitle(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("title"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
if (!res.error) {
|
||||||
|
const resultText =
|
||||||
|
res?.data?.data?.translations?.[0]?.text || "";
|
||||||
|
setTranslatedTitle(resultText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Translate title gagal:", err);
|
||||||
|
} finally {
|
||||||
|
close();
|
||||||
|
setIsLoadingTranslateTitle(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="px-3 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
|
||||||
|
>
|
||||||
|
{isLoadingTranslateTitle
|
||||||
|
? "Translating..."
|
||||||
|
: "Translate to English"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Judul Bahasa Indonesia */}
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="title"
|
||||||
|
render={({ field }) => (
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
placeholder="Masukkan Judul Bahasa Indonesia"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Versi English (muncul setelah klik translate) */}
|
||||||
|
{translatedTitle && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Label className="text-sm font-semibold">
|
||||||
|
English Title
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={translatedTitle}
|
||||||
|
onChange={(e) => setTranslatedTitle(e.target.value)}
|
||||||
|
placeholder="English version"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{errors.title?.message && (
|
||||||
|
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="space-y-2 py-3">
|
||||||
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -901,7 +999,7 @@ export default function FormVideo() {
|
||||||
{errors.title?.message && (
|
{errors.title?.message && (
|
||||||
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
<p className="text-red-400 text-sm">{errors.title.message}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="py-3 w-full space-y-2">
|
<div className="py-3 w-full space-y-2">
|
||||||
|
|
@ -1210,7 +1308,86 @@ export default function FormVideo() {
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Deskripsi dengan translate atas-bawah */}
|
||||||
<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) {
|
||||||
|
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>
|
||||||
|
|
||||||
|
{/* Editor Bahasa Indonesia */}
|
||||||
|
<div className="mt-2">
|
||||||
|
<Label className="text-sm font-semibold">
|
||||||
|
Indonesian Version
|
||||||
|
</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="descriptionOri"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={onChange}
|
||||||
|
initialData={value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Editor Bahasa Inggris (muncul setelah klik translate) */}
|
||||||
|
{translatedContent && (
|
||||||
|
<div className="mt-5">
|
||||||
|
<Label className="text-sm font-semibold">
|
||||||
|
English Version
|
||||||
|
</Label>
|
||||||
|
<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">
|
<div className="flex justify-between items-center">
|
||||||
<Label>
|
<Label>
|
||||||
{t("description", { defaultValue: "Description" })}
|
{t("description", { defaultValue: "Description" })}
|
||||||
|
|
@ -1253,7 +1430,6 @@ export default function FormVideo() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Pilihan bahasa untuk posting */}
|
|
||||||
<div className="flex items-center gap-4 mb-2">
|
<div className="flex items-center gap-4 mb-2">
|
||||||
<label className="flex items-center gap-2">
|
<label className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
|
|
@ -1266,7 +1442,6 @@ export default function FormVideo() {
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Editor Bahasa Indonesia */}
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="descriptionOri"
|
name="descriptionOri"
|
||||||
|
|
@ -1278,7 +1453,6 @@ export default function FormVideo() {
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Editor Bahasa Inggris */}
|
|
||||||
{translatedContent && (
|
{translatedContent && (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
|
|
@ -1291,7 +1465,7 @@ export default function FormVideo() {
|
||||||
value="en"
|
value="en"
|
||||||
checked={selectedLang === "en"}
|
checked={selectedLang === "en"}
|
||||||
onChange={() => setSelectedLang("en")}
|
onChange={() => setSelectedLang("en")}
|
||||||
disabled={!translatedContent} // kalau belum translate, disable
|
disabled={!translatedContent}
|
||||||
/>
|
/>
|
||||||
<span>Gunakan Bahasa Inggris</span>
|
<span>Gunakan Bahasa Inggris</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -1309,7 +1483,7 @@ export default function FormVideo() {
|
||||||
{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>
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ export default function FormVideoUpdate() {
|
||||||
const [translatedContent, setTranslatedContent] = React.useState("");
|
const [translatedContent, setTranslatedContent] = React.useState("");
|
||||||
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
|
||||||
const roleId = getCookiesDecrypt("urie");
|
const roleId = getCookiesDecrypt("urie");
|
||||||
|
const [translatedTitle, setTranslatedTitle] = useState("");
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", name: "SEMUA" },
|
{ id: "all", name: "SEMUA" },
|
||||||
|
|
@ -1030,15 +1031,21 @@ export default function FormVideoUpdate() {
|
||||||
|
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
|
|
||||||
const descFinal =
|
// const descFinal =
|
||||||
selectedLang === "en" && translatedContent
|
// selectedLang === "en" && translatedContent
|
||||||
? translatedContent
|
// ? translatedContent
|
||||||
: data.description;
|
// : data.description;
|
||||||
|
|
||||||
|
const descFinal = translatedContent || data.description;
|
||||||
|
const finalTitle = translatedTitle || data.title;
|
||||||
|
|
||||||
const requestData = {
|
const requestData = {
|
||||||
...data,
|
...data,
|
||||||
id: detail?.id,
|
id: detail?.id,
|
||||||
title: data.title,
|
// title: data.title,
|
||||||
|
// description: htmlToString(descFinal),
|
||||||
|
// htmlDescription: descFinal,
|
||||||
|
title: finalTitle,
|
||||||
description: htmlToString(descFinal),
|
description: htmlToString(descFinal),
|
||||||
htmlDescription: descFinal,
|
htmlDescription: descFinal,
|
||||||
fileTypeId,
|
fileTypeId,
|
||||||
|
|
@ -1325,6 +1332,81 @@ export default function FormVideoUpdate() {
|
||||||
<div className="gap-5 mb-5">
|
<div className="gap-5 mb-5">
|
||||||
{/* Input Title */}
|
{/* Input Title */}
|
||||||
<div className="space-y-2 py-3">
|
<div className="space-y-2 py-3">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
|
|
||||||
|
{roleId === "14" && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
loading();
|
||||||
|
setIsLoadingTranslate(true);
|
||||||
|
const res = await translateText({
|
||||||
|
text: getValues("title"),
|
||||||
|
sourceLang: "ID",
|
||||||
|
targetLang: "EN",
|
||||||
|
});
|
||||||
|
if (!res.error) {
|
||||||
|
const resultText =
|
||||||
|
res?.data?.data?.translations?.[0]?.text || "";
|
||||||
|
setTranslatedTitle(resultText);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
close();
|
||||||
|
console.error("Translate title 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 Title"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="title"
|
||||||
|
render={({ field }) => (
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
placeholder="Enter Title"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* English translated title appears below when available */}
|
||||||
|
{translatedTitle && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Label className="text-sm font-semibold">
|
||||||
|
English Version
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
size="md"
|
||||||
|
type="text"
|
||||||
|
value={translatedTitle}
|
||||||
|
onChange={(e) => setTranslatedTitle(e.target.value)}
|
||||||
|
placeholder="Translated Title"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{errors.title?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.title.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="space-y-2 py-3">
|
||||||
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
<Label>{t("title", { defaultValue: "Title" })}</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -1344,7 +1426,7 @@ export default function FormVideoUpdate() {
|
||||||
{errors.title.message}
|
{errors.title.message}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div> */}
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="py-3 w-full space-y-2">
|
<div className="py-3 w-full space-y-2">
|
||||||
<Label>{t("category", { defaultValue: "Category" })}</Label>
|
<Label>{t("category", { defaultValue: "Category" })}</Label>
|
||||||
|
|
@ -1407,7 +1489,7 @@ export default function FormVideoUpdate() {
|
||||||
if (!res.error) {
|
if (!res.error) {
|
||||||
const resultText =
|
const resultText =
|
||||||
res?.data?.data?.translations?.[0]?.text || "";
|
res?.data?.data?.translations?.[0]?.text || "";
|
||||||
|
// Overwrite data.description but still show both
|
||||||
setTranslatedContent(resultText);
|
setTranslatedContent(resultText);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -1422,55 +1504,34 @@ export default function FormVideoUpdate() {
|
||||||
>
|
>
|
||||||
{isLoadingTranslate
|
{isLoadingTranslate
|
||||||
? "Translating..."
|
? "Translating..."
|
||||||
: "Translate to English"}
|
: "Translate Description"}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</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 */}
|
{/* Editor Bahasa Indonesia */}
|
||||||
<Controller
|
<div className="mt-3">
|
||||||
control={control}
|
<Label className="text-sm font-semibold">
|
||||||
name="description"
|
Indonesian Version
|
||||||
render={({ field }) => (
|
</Label>
|
||||||
<CustomEditor
|
<Controller
|
||||||
onChange={field.onChange}
|
control={control}
|
||||||
initialData={field.value}
|
name="description"
|
||||||
/>
|
render={({ field }) => (
|
||||||
)}
|
<CustomEditor
|
||||||
/>
|
onChange={field.onChange}
|
||||||
|
initialData={field.value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Editor Bahasa Inggris */}
|
{/* English translated version muncul setelah translate */}
|
||||||
{translatedContent && (
|
{translatedContent && (
|
||||||
<div className="mt-4">
|
<div className="mt-5">
|
||||||
<div className="flex flex-col">
|
<Label className="text-sm font-semibold">
|
||||||
<Label className="text-[15px]">English Version</Label>
|
English Version
|
||||||
<label className="flex items-center gap-2">
|
</Label>
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
value="en"
|
|
||||||
checked={selectedLang === "en"}
|
|
||||||
onChange={() => setSelectedLang("en")}
|
|
||||||
disabled={!translatedContent}
|
|
||||||
/>
|
|
||||||
<span>Gunakan Bahasa Inggris</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CustomEditor
|
<CustomEditor
|
||||||
onChange={(val: any) => setTranslatedContent(val)}
|
onChange={(val: any) => setTranslatedContent(val)}
|
||||||
initialData={translatedContent}
|
initialData={translatedContent}
|
||||||
|
|
@ -1484,6 +1545,7 @@ export default function FormVideoUpdate() {
|
||||||
</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" })}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue