feat: add button translate in all content update and upload

This commit is contained in:
Sabda Yagra 2025-10-15 14:02:41 +07:00
parent 92811802cc
commit c6e0e123c3
7 changed files with 724 additions and 261 deletions

View File

@ -145,10 +145,10 @@ export default function FormAudio() {
const [publishedFor, setPublishedFor] = useState<string[]>([]);
const [fileError, setFileError] = useState<string | null>(null);
type FileWithPreview = File & { preview: string };
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
const [translatedContent, setTranslatedContent] = React.useState("");
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
const [translatedTitle, setTranslatedTitle] = useState("");
const options: Option[] = [
{ id: "all", label: "SEMUA" },
@ -618,29 +618,49 @@ export default function FormAudio() {
const save = async (data: AudioSchema) => {
loading();
const finalTags = tags.join(", ");
const finalTitle = isSwitchOn ? title : data.title;
// const finalTitle = isSwitchOn ? title : data.title;
// pilih description dasar
let finalDescription = isSwitchOn
? data.description
: selectedFileType === "rewrite"
? data.rewriteDescription
: data.descriptionOri;
// // pilih description dasar
// let finalDescription = isSwitchOn
// ? data.description
// : selectedFileType === "rewrite"
// ? data.rewriteDescription
// : 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
if (translatedContent) {
data.descriptionOri = translatedContent; // update ke form
finalDescription = translatedContent; // pakai untuk request
data.descriptionOri = translatedContent;
console.log(
"🌍 Translate dimasukkan ke descriptionOri:",
translatedContent
);
}
if (!finalDescription?.trim()) {
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
return;
}
// if (!finalDescription?.trim()) {
// MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
// return;
// }
let requestData: {
title: string;
@ -963,7 +983,44 @@ export default function FormAudio() {
<div className="gap-5 mb-5">
{/* Input Title */}
<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
control={control}
name="title"
@ -973,10 +1030,27 @@ export default function FormAudio() {
type="text"
value={field.value}
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 && (
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}

View File

@ -24,10 +24,6 @@ import {
SelectValue,
} from "@/components/ui/select";
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 {
createMedia,
@ -196,11 +192,11 @@ export default function FormAudioUpdate() {
useState(false);
const [mainCheckboxChangeType, setMainCheckboxChangeType] =
useState<string>("");
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
const [translatedContent, setTranslatedContent] = React.useState("");
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
const roleId = getCookiesDecrypt("urie");
const [translatedTitle, setTranslatedTitle] = useState("");
const options: Option[] = [
{ id: "all", name: "SEMUA" },
@ -1223,16 +1219,19 @@ export default function FormAudioUpdate() {
const finalTags = tags.join(", ");
// ✅ tentukan isi description sesuai pilihan bahasa
const descFinal =
selectedLang === "en" && translatedContent
? translatedContent
: data.description;
// const descFinal =
// selectedLang === "en" && translatedContent
// ? translatedContent
// : data.description;
const descFinal = translatedContent || data.description;
const finalTitle = translatedTitle || data.title;
const requestData = {
...data,
id: detail?.id,
title: data.title,
description: htmlToString(descFinal),
title: finalTitle,
description: htmlToString(descFinal),
htmlDescription: descFinal,
fileTypeId,
categoryId: selectedTarget,
@ -1533,7 +1532,43 @@ export default function FormAudioUpdate() {
<div className="gap-5 mb-5">
{/* Input Title */}
<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
control={control}
name="title"
@ -1541,18 +1576,36 @@ export default function FormAudioUpdate() {
<Input
size="md"
type="text"
value={field?.value}
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="flex items-center">
<div className="py-3 w-full space-y-2">
<Label>{t("category", { defaultValue: "Category" })}</Label>
@ -1616,7 +1669,7 @@ export default function FormAudioUpdate() {
if (!res.error) {
const resultText =
res?.data?.data?.translations?.[0]?.text || "";
// Overwrite data.description but still show both
setTranslatedContent(resultText);
}
} catch (err) {
@ -1631,55 +1684,34 @@ export default function FormAudioUpdate() {
>
{isLoadingTranslate
? "Translating..."
: "Translate to English"}
: "Translate Description"}
</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="description"
render={({ field }) => (
<CustomEditor
onChange={field.onChange}
initialData={field.value}
/>
)}
/>
<div className="mt-3">
<Label className="text-sm font-semibold">
Indonesian Version
</Label>
<Controller
control={control}
name="description"
render={({ field }) => (
<CustomEditor
onChange={field.onChange}
initialData={field.value}
/>
)}
/>
</div>
{/* Editor Bahasa Inggris */}
{/* English translated version muncul setelah translate */}
{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}
/>
<span>Gunakan Bahasa Inggris</span>
</label>
</div>
<div className="mt-5">
<Label className="text-sm font-semibold">
English Version
</Label>
<CustomEditor
onChange={(val: any) => setTranslatedContent(val)}
initialData={translatedContent}

View File

@ -1353,7 +1353,6 @@ export default function FormImage() {
value={selectedFileType}
className="grid-cols-1"
>
{/* HAPUS radio, ganti jadi preview side-by-side */}
<div className="py-3 space-y-2">
<div className="flex justify-between items-center">
<Label className="text-[15px]">

View File

@ -26,8 +26,6 @@ import {
} from "@/components/ui/select";
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 {
@ -140,13 +138,12 @@ export default function FormTeks() {
let uploadPersen = 0;
const [isStartUpload, setIsStartUpload] = useState(false);
const [counterProgress, setCounterProgress] = useState(0);
const [files, setFiles] = useState<FileWithPreview[]>([]);
const [publishedFor, setPublishedFor] = useState<string[]>([]);
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
const [translatedContent, setTranslatedContent] = React.useState("");
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
const [translatedTitle, setTranslatedTitle] = useState("");
const options: Option[] = [
{ id: "all", label: "SEMUA" },
@ -647,13 +644,34 @@ export default function FormTeks() {
}
const finalTags = tags.join(", ");
const finalTitle = isSwitchOn ? title : data.title;
// const finalTitle = isSwitchOn ? title : data.title;
// const finalDescription = articleBody || data.description;
const finalDescription = isSwitchOn
? data.description
: selectedFileType === "rewrite"
? data.rewriteDescription
: data.descriptionOri;
// const finalDescription = isSwitchOn
// ? data.description
// : selectedFileType === "rewrite"
// ? data.rewriteDescription
// : 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()) {
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
@ -974,6 +992,80 @@ export default function FormTeks() {
<div className="gap-5 mb-5">
{/* Input Title */}
<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>
<Controller
control={control}
@ -991,7 +1083,7 @@ export default function FormTeks() {
{errors.title?.message && (
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}
</div>
</div> */}
<div className="flex items-center">
<div className="py-3 w-full space-y-2">
@ -1317,12 +1409,10 @@ export default function FormTeks() {
sourceLang: "ID",
targetLang: "EN",
});
if (!res.error) {
const resultText =
res?.data?.data?.translations?.[0]?.text ||
"";
setTranslatedContent(resultText);
}
} catch (err) {
@ -1337,57 +1427,34 @@ export default function FormTeks() {
>
{isLoadingTranslate
? "Translating..."
: "Translate to English"}
: "Translate Description"}
</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")}
{/* Deskripsi 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}
/>
<span>Gunakan Bahasa Indonesia</span>
</label>
</div>
)}
)}
/>
</div>
{/* Editor Bahasa Indonesia */}
<Controller
control={control}
name="descriptionOri"
render={({ field: { onChange, value } }) => (
<CustomEditor
onChange={onChange}
initialData={value}
/>
)}
/>
{/* Editor Bahasa Inggris */}
{/* Versi Inggris muncul setelah translate */}
{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>
<div className="mt-5">
<Label className="text-sm font-semibold">
English Version
</Label>
<CustomEditor
onChange={(val: any) => setTranslatedContent(val)}
initialData={translatedContent}
@ -1401,6 +1468,7 @@ export default function FormTeks() {
</p>
)}
</div>
{/* <div className="py-3 space-y-2">
<Label>
{t("description", { defaultValue: "Description" })}

View File

@ -203,6 +203,7 @@ export default function FormTeksUpdate() {
const [translatedContent, setTranslatedContent] = React.useState("");
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
const roleId = getCookiesDecrypt("urie");
const [translatedTitle, setTranslatedTitle] = useState("");
let fileTypeId = "3";
const isDetailOfRegionShowed = false;
@ -1250,18 +1251,18 @@ export default function FormTeksUpdate() {
loading();
const finalTags = tags.join(", ");
// ✅ tentukan isi description sesuai pilihan bahasa
const descFinal =
selectedLang === "en" && translatedContent
? translatedContent
: data.description;
// const descFinal =
// selectedLang === "en" && translatedContent
// ? translatedContent
// : data.description;
const descFinal = translatedContent || data.description;
const finalTitle = translatedTitle || data.title;
const requestData = {
...data,
id: detail?.id,
title: data.title,
description: htmlToString(descFinal), // plain text
htmlDescription: descFinal, // HTML (dipakai di editor/preview)
title: finalTitle,
description: htmlToString(descFinal),
htmlDescription: descFinal,
fileTypeId,
categoryId: selectedTarget,
subCategoryId: selectedTarget,
@ -1531,6 +1532,81 @@ export default function FormTeksUpdate() {
<div className="gap-5 mb-5">
{/* Input Title */}
<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>
<Controller
control={control}
@ -1550,7 +1626,7 @@ export default function FormTeksUpdate() {
{errors.title.message}
</p>
)}
</div>
</div> */}
<div className="flex items-center">
<div className="py-3 w-full space-y-2">
<Label>{t("category", { defaultValue: "Category" })}</Label>
@ -1591,7 +1667,6 @@ export default function FormTeksUpdate() {
</Select>
</div>
</div>
<div className="py-3 space-y-2">
<div className="flex justify-between items-center">
<Label>
@ -1614,7 +1689,7 @@ export default function FormTeksUpdate() {
if (!res.error) {
const resultText =
res?.data?.data?.translations?.[0]?.text || "";
// Overwrite data.description but still show both
setTranslatedContent(resultText);
}
} catch (err) {
@ -1629,55 +1704,34 @@ export default function FormTeksUpdate() {
>
{isLoadingTranslate
? "Translating..."
: "Translate to English"}
: "Translate Description"}
</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="description"
render={({ field }) => (
<CustomEditor
onChange={field.onChange}
initialData={field.value}
/>
)}
/>
<div className="mt-3">
<Label className="text-sm font-semibold">
Indonesian Version
</Label>
<Controller
control={control}
name="description"
render={({ field }) => (
<CustomEditor
onChange={field.onChange}
initialData={field.value}
/>
)}
/>
</div>
{/* Editor Bahasa Inggris */}
{/* English translated version muncul setelah translate */}
{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}
/>
<span>Gunakan Bahasa Inggris</span>
</label>
</div>
<div className="mt-5">
<Label className="text-sm font-semibold">
English Version
</Label>
<CustomEditor
onChange={(val: any) => setTranslatedContent(val)}
initialData={translatedContent}

View File

@ -26,8 +26,6 @@ import {
} from "@/components/ui/select";
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 {
@ -36,7 +34,6 @@ import {
listEnableCategory,
uploadThumbnail,
} from "@/service/content/content";
import { uploadThumbnailBlog } from "@/service/blog/blog";
import { Textarea } from "@/components/ui/textarea";
import {
generateDataArticle,
@ -52,10 +49,8 @@ import { Icon } from "@iconify/react";
import { CloudUpload } from "lucide-react";
import Image from "next/image";
import { close, error, loading } from "@/config/swal";
import { Item } from "@radix-ui/react-dropdown-menu";
import dynamic from "next/dynamic";
import { getCsrfToken } from "@/service/auth";
import { Link } from "@/i18n/routing";
import { useTranslations } from "next-intl";
import { htmlToString } from "@/utils/globals";
@ -146,10 +141,12 @@ export default function FormVideo() {
const [counterProgress, setCounterProgress] = useState(0);
const [publishedFor, setPublishedFor] = useState<string[]>([]);
const [files, setFiles] = useState<FileWithPreview[]>([]);
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
const [translatedContent, setTranslatedContent] = React.useState("");
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
// 🔹 State untuk translate Title
const [translatedTitle, setTranslatedTitle] = useState("");
const [isLoadingTranslateTitle, setIsLoadingTranslateTitle] = useState(false);
const options: Option[] = [
{ id: "all", label: "SEMUA" },
@ -536,28 +533,55 @@ export default function FormVideo() {
}
loading();
const finalTags = data.tags.join(", ");
const finalTitle = isSwitchOn ? title : data.title;
// const finalTitle = isSwitchOn ? title : data.title;
// const finalDescription = articleBody || data.description;
const finalDescription = isSwitchOn
? data.description
: selectedFileType === "rewrite"
? data.rewriteDescription
: data.descriptionOri;
// const finalDescription = 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 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()) {
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
);
}
console.log("📝 Deskripsi final yang dikirim:", finalDescription);
let requestData: {
title: string;
description: string;
@ -883,7 +907,81 @@ export default function FormVideo() {
{t("form-video", { defaultValue: "Form Video" })}
</p>
<div className="gap-5 mb-5">
{/* Input Title dengan tombol translate */}
<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>
<Controller
control={control}
@ -901,7 +999,7 @@ export default function FormVideo() {
{errors.title?.message && (
<p className="text-red-400 text-sm">{errors.title.message}</p>
)}
</div>
</div> */}
<div className="flex items-center">
<div className="py-3 w-full space-y-2">
@ -1210,7 +1308,86 @@ export default function FormVideo() {
</Label>
</div>
{/* Deskripsi dengan translate atas-bawah */}
<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">
<Label>
{t("description", { defaultValue: "Description" })}
@ -1253,7 +1430,6 @@ export default function FormVideo() {
)}
</div>
{/* Pilihan bahasa untuk posting */}
<div className="flex items-center gap-4 mb-2">
<label className="flex items-center gap-2">
<input
@ -1266,7 +1442,6 @@ export default function FormVideo() {
</label>
</div>
{/* Editor Bahasa Indonesia */}
<Controller
control={control}
name="descriptionOri"
@ -1278,7 +1453,6 @@ export default function FormVideo() {
)}
/>
{/* Editor Bahasa Inggris */}
{translatedContent && (
<div className="mt-4">
<div className="flex flex-col">
@ -1291,7 +1465,7 @@ export default function FormVideo() {
value="en"
checked={selectedLang === "en"}
onChange={() => setSelectedLang("en")}
disabled={!translatedContent} // kalau belum translate, disable
disabled={!translatedContent}
/>
<span>Gunakan Bahasa Inggris</span>
</label>
@ -1309,7 +1483,7 @@ export default function FormVideo() {
{errors.description.message}
</p>
)}
</div>
</div> */}
{/* <div className="py-3 space-y-2">
<Label>

View File

@ -226,6 +226,7 @@ export default function FormVideoUpdate() {
const [translatedContent, setTranslatedContent] = React.useState("");
const [selectedLang, setSelectedLang] = React.useState<"id" | "en">("id");
const roleId = getCookiesDecrypt("urie");
const [translatedTitle, setTranslatedTitle] = useState("");
const options: Option[] = [
{ id: "all", name: "SEMUA" },
@ -1023,22 +1024,28 @@ export default function FormVideoUpdate() {
// // router.push("/en/contributor/content/video");
// // });
// };
const save = async (data: VideoSchema) => {
loading();
const finalTags = tags.join(", ");
const descFinal =
selectedLang === "en" && translatedContent
? translatedContent
: data.description;
// const descFinal =
// selectedLang === "en" && translatedContent
// ? translatedContent
// : data.description;
const descFinal = translatedContent || data.description;
const finalTitle = translatedTitle || data.title;
const requestData = {
...data,
id: detail?.id,
title: data.title,
description: htmlToString(descFinal),
// title: data.title,
// description: htmlToString(descFinal),
// htmlDescription: descFinal,
title: finalTitle,
description: htmlToString(descFinal),
htmlDescription: descFinal,
fileTypeId,
categoryId: selectedTarget,
@ -1324,6 +1331,81 @@ export default function FormVideoUpdate() {
<div className="gap-5 mb-5">
{/* Input Title */}
<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>
<Controller
control={control}
@ -1343,7 +1425,7 @@ export default function FormVideoUpdate() {
{errors.title.message}
</p>
)}
</div>
</div> */}
<div className="flex items-center">
<div className="py-3 w-full space-y-2">
<Label>{t("category", { defaultValue: "Category" })}</Label>
@ -1406,7 +1488,7 @@ export default function FormVideoUpdate() {
if (!res.error) {
const resultText =
res?.data?.data?.translations?.[0]?.text || "";
// Overwrite data.description but still show both
setTranslatedContent(resultText);
}
} catch (err) {
@ -1421,55 +1503,34 @@ export default function FormVideoUpdate() {
>
{isLoadingTranslate
? "Translating..."
: "Translate to English"}
: "Translate Description"}
</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="description"
render={({ field }) => (
<CustomEditor
onChange={field.onChange}
initialData={field.value}
/>
)}
/>
<div className="mt-3">
<Label className="text-sm font-semibold">
Indonesian Version
</Label>
<Controller
control={control}
name="description"
render={({ field }) => (
<CustomEditor
onChange={field.onChange}
initialData={field.value}
/>
)}
/>
</div>
{/* Editor Bahasa Inggris */}
{/* English translated version muncul setelah translate */}
{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}
/>
<span>Gunakan Bahasa Inggris</span>
</label>
</div>
<div className="mt-5">
<Label className="text-sm font-semibold">
English Version
</Label>
<CustomEditor
onChange={(val: any) => setTranslatedContent(val)}
initialData={translatedContent}
@ -1483,6 +1544,7 @@ export default function FormVideoUpdate() {
</p>
)}
</div>
{/* <div className="py-3 space-y-2">
<Label>
{t("description", { defaultValue: "Description" })}