Compare commits

...

15 Commits

15 changed files with 693 additions and 118 deletions

View File

@ -22,6 +22,8 @@ import { PaginationState } from "@tanstack/react-table";
import page from "../page"; import page from "../page";
import CustomPagination from "@/components/table/custom-pagination"; import CustomPagination from "@/components/table/custom-pagination";
import { close, loading } from "@/config/swal"; import { close, loading } from "@/config/swal";
import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2";
export default function TrackingBeritaCard() { export default function TrackingBeritaCard() {
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
@ -30,6 +32,7 @@ export default function TrackingBeritaCard() {
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [totalPage, setTotalPage] = useState(1); const [totalPage, setTotalPage] = useState(1);
const [showData, setShowData] = useState("6"); const [showData, setShowData] = useState("6");
const MySwal = withReactContent(Swal);
useEffect(() => { useEffect(() => {
initFecth(); initFecth();
@ -70,13 +73,45 @@ export default function TrackingBeritaCard() {
); );
}; };
// const doSave = async () => {
// if (selectedItems.length === 0) {
// toast("Pilih minimal 1 berita untuk disimpan.");
// return;
// }
// try {
// const promises = selectedItems.map((id) =>
// mediaTrackingSave({
// mediaUploadId: id,
// duration: 24,
// scrapingPeriod: 3,
// })
// );
// await Promise.all(promises);
// toast("Berhasil Menambahkan", {
// description: "",
// });
// setSelectedItems([]);
// initFecth();
// } catch (err: any) {
// error(err?.message || "Gagal menyimpan data.");
// }
// };
const doSave = async () => { const doSave = async () => {
if (selectedItems.length === 0) { if (selectedItems.length === 0) {
toast("Pilih minimal 1 berita untuk disimpan."); MySwal.fire(
"Peringatan",
"Pilih minimal 1 berita untuk disimpan.",
"warning"
);
return; return;
} }
try { try {
loading();
const promises = selectedItems.map((id) => const promises = selectedItems.map((id) =>
mediaTrackingSave({ mediaTrackingSave({
mediaUploadId: id, mediaUploadId: id,
@ -86,13 +121,25 @@ export default function TrackingBeritaCard() {
); );
await Promise.all(promises); await Promise.all(promises);
toast("Berhasil Menambahkan", { close();
description: "",
await MySwal.fire({
icon: "success",
title: "Berhasil!",
text: "Tracking berita berhasil ditambahkan.",
confirmButtonColor: "#2563eb",
}); });
setSelectedItems([]); setSelectedItems([]);
initFecth(); initFecth();
} catch (err: any) { } catch (err: any) {
error(err?.message || "Gagal menyimpan data."); close();
MySwal.fire({
icon: "error",
title: "Gagal!",
text: err?.message || "Terjadi kesalahan saat menyimpan data.",
confirmButtonColor: "#dc2626",
});
} }
}; };

View File

@ -241,7 +241,7 @@ const DetailVideo = () => {
url={detailDataVideo?.files[selectedVideo]?.url} url={detailDataVideo?.files[selectedVideo]?.url}
/> */} /> */}
<video <video
className="object-fill h-full w-full rounded-md" className="w-full h-[600px] object-contain"
src={detailDataVideo?.files[0]?.url} src={detailDataVideo?.files[0]?.url}
controls controls
/> />

View File

@ -713,6 +713,7 @@ export default function FilterPage() {
startDateString={startDateString} startDateString={startDateString}
endDateString={endDateString} endDateString={endDateString}
monthYearFilter={monthYearFilter} monthYearFilter={monthYearFilter}
isRegionalCall={true}
/> />
<FilterVideoComponent <FilterVideoComponent
categoryFilter={categoryFilter} categoryFilter={categoryFilter}
@ -720,6 +721,7 @@ export default function FilterPage() {
startDateString={startDateString} startDateString={startDateString}
endDateString={endDateString} endDateString={endDateString}
monthYearFilter={monthYearFilter} monthYearFilter={monthYearFilter}
isRegionalCall={true}
/> />
<FilterDocumentComponent <FilterDocumentComponent
categoryFilter={categoryFilter} categoryFilter={categoryFilter}
@ -727,6 +729,7 @@ export default function FilterPage() {
startDateString={startDateString} startDateString={startDateString}
endDateString={endDateString} endDateString={endDateString}
monthYearFilter={monthYearFilter} monthYearFilter={monthYearFilter}
isRegionalCall={true}
/> />
<FilterAudioComponent <FilterAudioComponent
categoryFilter={categoryFilter} categoryFilter={categoryFilter}
@ -734,6 +737,7 @@ export default function FilterPage() {
startDateString={startDateString} startDateString={startDateString}
endDateString={endDateString} endDateString={endDateString}
monthYearFilter={monthYearFilter} monthYearFilter={monthYearFilter}
isRegionalCall={true}
/> />
<FilterIndeksComponent <FilterIndeksComponent
categoryFilter={categoryFilter} categoryFilter={categoryFilter}

View File

@ -5,7 +5,7 @@ import { CKEditor } from "@ckeditor/ckeditor5-react";
import Editor from "ckeditor5-custom-build"; import Editor from "ckeditor5-custom-build";
function CustomEditor(props) { function CustomEditor(props) {
const maxHeight = props.maxHeight || 600; const maxHeight = props.maxHeight || 600;
return ( return (
<div className="ckeditor-wrapper"> <div className="ckeditor-wrapper">
@ -168,4 +168,4 @@ function CustomEditor(props) {
); );
} }
export default CustomEditor; export default CustomEditor;

View File

@ -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">

View File

@ -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 && (

View File

@ -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">

View File

@ -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">

View File

@ -22,6 +22,7 @@ export default function FilterAudioComponent(props: {
startDateString?: string; startDateString?: string;
endDateString?: string; endDateString?: string;
monthYearFilter?: any; monthYearFilter?: any;
isRegionalCall?: any;
}) { }) {
const { const {
categoryFilter, categoryFilter,
@ -29,6 +30,7 @@ export default function FilterAudioComponent(props: {
startDateString, startDateString,
endDateString, endDateString,
monthYearFilter, monthYearFilter,
isRegionalCall,
} = props; } = props;
const [newContent, setNewContent] = useState<any>(); const [newContent, setNewContent] = useState<any>();
const asPath = usePathname(); const asPath = usePathname();
@ -42,7 +44,7 @@ export default function FilterAudioComponent(props: {
const categorie = searchParams?.get("category"); const categorie = searchParams?.get("category");
const group = searchParams?.get("group"); const group = searchParams?.get("group");
const [totalContent, setTotalContent] = useState(); const [totalContent, setTotalContent] = useState();
const isRegional = group || asPath.includes("/polda/"); const isRegional = isRegionalCall || group || asPath.includes("/polda/");
const searchType = isRegional ? "regional" : "filter"; const searchType = isRegional ? "regional" : "filter";
const router = useRouter(); const router = useRouter();
const poldaName = params?.polda_name; const poldaName = params?.polda_name;
@ -52,7 +54,7 @@ export default function FilterAudioComponent(props: {
? `/polda/${poldaName}` ? `/polda/${poldaName}`
: satkerName : satkerName
? `/satker/${satkerName}` ? `/satker/${satkerName}`
: "/"; : "";
useEffect(() => { useEffect(() => {
if (searchType === "regional") { if (searchType === "regional") {
@ -75,11 +77,16 @@ export default function FilterAudioComponent(props: {
let startDateFilter = startDateString ? startDateString : ""; let startDateFilter = startDateString ? startDateString : "";
let endDateFilter = endDateString ? endDateString : ""; let endDateFilter = endDateString ? endDateString : "";
let monthFilter = monthYearFilter ? monthYearFilter : ""; let monthFilter = monthYearFilter ? monthYearFilter : "";
const search = title == undefined ? "" : title;
const filter =
categoryFilter?.length > 0
? categoryFilter?.sort().join(",")
: categorie || "";
const response = await listDataRegional( const response = await listDataRegional(
"4", "4",
"", search,
"", filter,
"", "",
"", "",
startDateFilter, startDateFilter,
@ -93,7 +100,8 @@ export default function FilterAudioComponent(props: {
const contentData = data?.content; const contentData = data?.content;
setNewContent(contentData); setNewContent(contentData);
setTotalData(data?.totalElements); setTotalData(data?.totalElements);
// setLoading(false); setTotalPage(data?.totalPages);
setTotalContent(data?.totalElements);
} }
useEffect(() => { useEffect(() => {
@ -234,10 +242,12 @@ export default function FilterAudioComponent(props: {
<CarouselContent> <CarouselContent>
{newContent?.map((audio: any) => ( {newContent?.map((audio: any) => (
<CarouselItem key={audio?.id} className="md:basis-1/2 lg:basis-1/3"> <CarouselItem key={audio?.id} className="md:basis-1/2 lg:basis-1/3">
<div <Link
onClick={() => href={`${prefixPath}${audio?.slug}`}
router.push(prefixPath + `/audio/detail/${audio?.slug}`) // href={prefixPath + `/audio/detail/${audio?.slug}`}
} // onClick={() =>
// router.push(prefixPath + `/audio/detail/${audio?.slug}`)
// }
className="cursor-pointer bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300 overflow-hidden" className="cursor-pointer bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300 overflow-hidden"
> >
{/* Icon Background */} {/* Icon Background */}
@ -265,7 +275,7 @@ export default function FilterAudioComponent(props: {
{audio?.title} {audio?.title}
</p> </p>
</div> </div>
</div> </Link>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>

View File

@ -22,6 +22,7 @@ export default function FilterDocumentComponent(props: {
startDateString?: string; startDateString?: string;
endDateString?: string; endDateString?: string;
monthYearFilter?: any; monthYearFilter?: any;
isRegionalCall?: any;
}) { }) {
const { const {
categoryFilter, categoryFilter,
@ -29,6 +30,7 @@ export default function FilterDocumentComponent(props: {
startDateString, startDateString,
endDateString, endDateString,
monthYearFilter, monthYearFilter,
isRegionalCall,
} = props; } = props;
const [newContent, setNewContent] = useState<any>(); const [newContent, setNewContent] = useState<any>();
const asPath = usePathname(); const asPath = usePathname();
@ -42,7 +44,7 @@ export default function FilterDocumentComponent(props: {
const categorie = searchParams?.get("category"); const categorie = searchParams?.get("category");
const group = searchParams?.get("group"); const group = searchParams?.get("group");
const [totalContent, setTotalContent] = useState(); const [totalContent, setTotalContent] = useState();
const isRegional = group || asPath.includes("/polda/"); const isRegional = isRegionalCall || group || asPath.includes("/polda/");
const searchType = isRegional ? "regional" : "filter"; const searchType = isRegional ? "regional" : "filter";
const router = useRouter(); const router = useRouter();
@ -53,7 +55,7 @@ export default function FilterDocumentComponent(props: {
? `/polda/${poldaName}` ? `/polda/${poldaName}`
: satkerName : satkerName
? `/satker/${satkerName}` ? `/satker/${satkerName}`
: "/"; : "";
useEffect(() => { useEffect(() => {
if (searchType === "regional") { if (searchType === "regional") {
@ -77,10 +79,16 @@ export default function FilterDocumentComponent(props: {
let endDateFilter = endDateString ? endDateString : ""; let endDateFilter = endDateString ? endDateString : "";
let monthFilter = monthYearFilter ? monthYearFilter : ""; let monthFilter = monthYearFilter ? monthYearFilter : "";
const search = title == undefined ? "" : title;
const filter =
categoryFilter?.length > 0
? categoryFilter?.sort().join(",")
: categorie || "";
const response = await listDataRegional( const response = await listDataRegional(
"3", "3",
"", search,
"", filter,
"", "",
"", "",
startDateFilter, startDateFilter,
@ -94,7 +102,8 @@ export default function FilterDocumentComponent(props: {
const contentData = data?.content; const contentData = data?.content;
setNewContent(contentData); setNewContent(contentData);
setTotalData(data?.totalElements); setTotalData(data?.totalElements);
// setLoading(false); setTotalPage(data?.totalPages);
setTotalContent(data?.totalElements);
} }
async function getDataAll() { async function getDataAll() {
@ -204,10 +213,12 @@ export default function FilterDocumentComponent(props: {
<CarouselContent> <CarouselContent>
{newContent?.map((text: any) => ( {newContent?.map((text: any) => (
<CarouselItem key={text?.id} className="md:basis-1/2 lg:basis-1/3"> <CarouselItem key={text?.id} className="md:basis-1/2 lg:basis-1/3">
<div <Link
onClick={() => href={`${prefixPath}${text?.slug}`}
router.push(prefixPath + `/document/detail/${text?.slug}`) // href={prefixPath + `/document/detail/${text?.slug}`}
} // onClick={() =>
// router.push(prefixPath + `/document/detail/${text?.slug}`)
// }
className="cursor-pointer rounded-lg shadow-md overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500" className="cursor-pointer rounded-lg shadow-md overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500"
> >
{/* Ikon di tengah dengan latar kuning */} {/* Ikon di tengah dengan latar kuning */}
@ -237,7 +248,7 @@ export default function FilterDocumentComponent(props: {
{text?.title} {text?.title}
</div> </div>
</div> </div>
</div> </Link>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>

View File

@ -21,6 +21,7 @@ export default function FilterImageComponent(props: {
startDateString?: string; startDateString?: string;
endDateString?: string; endDateString?: string;
monthYearFilter?: any; monthYearFilter?: any;
isRegionalCall?: any;
}) { }) {
const { const {
categoryFilter, categoryFilter,
@ -28,6 +29,7 @@ export default function FilterImageComponent(props: {
startDateString, startDateString,
endDateString, endDateString,
monthYearFilter, monthYearFilter,
isRegionalCall,
} = props; } = props;
const router = useRouter(); const router = useRouter();
const [newContent, setNewContent] = useState<any>(); const [newContent, setNewContent] = useState<any>();
@ -43,7 +45,7 @@ export default function FilterImageComponent(props: {
const [totalContent, setTotalContent] = useState(); const [totalContent, setTotalContent] = useState();
const poldaName = params?.polda_name; const poldaName = params?.polda_name;
const satkerName = params?.satker_name; const satkerName = params?.satker_name;
const isRegional = group || asPath.includes("/polda/"); const isRegional = isRegionalCall || group || asPath.includes("/polda/");
const searchType = isRegional ? "regional" : "filter"; const searchType = isRegional ? "regional" : "filter";
useEffect(() => { useEffect(() => {
@ -115,10 +117,16 @@ export default function FilterImageComponent(props: {
let endDateFilter = endDateString ? endDateString : ""; let endDateFilter = endDateString ? endDateString : "";
let monthFilter = monthYearFilter ? monthYearFilter : ""; let monthFilter = monthYearFilter ? monthYearFilter : "";
const search = title == undefined ? "" : title;
const filter =
categoryFilter?.length > 0
? categoryFilter?.sort().join(",")
: categorie || "";
const response = await listDataRegional( const response = await listDataRegional(
"1", "1",
"", search,
"", filter,
"", "",
"", "",
startDateFilter, startDateFilter,
@ -132,7 +140,8 @@ export default function FilterImageComponent(props: {
const contentData = data?.content; const contentData = data?.content;
setNewContent(contentData); setNewContent(contentData);
setTotalData(data?.totalElements); setTotalData(data?.totalElements);
// setLoading(false); setTotalPage(data?.totalPages);
setTotalContent(data?.totalElements);
} }
const basePath = asPath.includes("/polda/") const basePath = asPath.includes("/polda/")
@ -152,7 +161,7 @@ export default function FilterImageComponent(props: {
? `/polda/${poldaName}` ? `/polda/${poldaName}`
: satkerName : satkerName
? `/satker/${satkerName}` ? `/satker/${satkerName}`
: "/"; : "";
return newContent?.length > 0 ? ( return newContent?.length > 0 ? (
<div className="flex flex-col gap-3 w-full"> <div className="flex flex-col gap-3 w-full">
@ -191,7 +200,7 @@ export default function FilterImageComponent(props: {
{newContent?.map((image: any) => ( {newContent?.map((image: any) => (
<CarouselItem key={image?.id} className="md:basis-1/2 lg:basis-1/3"> <CarouselItem key={image?.id} className="md:basis-1/2 lg:basis-1/3">
<Link <Link
href={prefixPath + `/image/detail/${image?.slug}`} href={`${prefixPath}${image?.slug}`}
// onClick={() => // onClick={() =>
// router.push(prefixPath + `/image/detail/${image?.slug}`) // router.push(prefixPath + `/image/detail/${image?.slug}`)
// } // }
@ -203,17 +212,19 @@ export default function FilterImageComponent(props: {
// whileHover={{ scale: 0.95 }} // whileHover={{ scale: 0.95 }}
// transition={{ duration: 0.3 }} // transition={{ duration: 0.3 }}
> >
<Image {image?.thumbnailLink && (
priority={true} <Image
// placeholder={`data:image/svg+xml;base64,${toBase64( priority={true}
// shimmer(700, 475) // placeholder={`data:image/svg+xml;base64,${toBase64(
// )}`} // shimmer(700, 475)
width={2560} // )}`}
height={1440} width={2560}
alt="image" height={1440}
src={image?.smallThumbnailLink} alt="image"
className="w-full h-full object-cover" src={image?.thumbnailLink}
/> className="w-full h-full object-cover"
/>
)}
</div> </div>
{/* Badge category */} {/* Badge category */}

View File

@ -50,7 +50,7 @@ export default function IndeksCarouselComponent(props: {
? `/polda/${poldaName}` ? `/polda/${poldaName}`
: satkerName : satkerName
? `/satker/${satkerName}` ? `/satker/${satkerName}`
: "/"; : "";
// useEffect(() => { // useEffect(() => {
// initFetch(); // initFetch();
@ -166,19 +166,21 @@ export default function IndeksCarouselComponent(props: {
<CarouselContent> <CarouselContent>
{newContent.map((image: any) => ( {newContent.map((image: any) => (
<CarouselItem key={image?.id} className="md:basis-1/2 lg:basis-1/3"> <CarouselItem key={image?.id} className="md:basis-1/2 lg:basis-1/3">
<div <Link href={`/indeks/detail/${image?.slug}`}
onClick={() => router.push(`/indeks/detail/${image?.slug}`)} // onClick={() => router.push(`/indeks/detail/${image?.slug}`)}
className="cursor-pointer relative group overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300" className="cursor-pointer relative group overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300"
> >
<div className="w-full h-48 lg:h-60"> <div className="w-full h-48 lg:h-60">
<Image {image?.thumbnailLink &&
priority <Image
width={2560} priority
height={1440} width={2560}
alt="image" height={1440}
src={image?.thumbnailLink} alt="image"
className="w-full h-full object-cover" src={image?.thumbnailLink}
/> className="w-full h-full object-cover"
/>
}
</div> </div>
<div className="p-4 h-full flex flex-col justify-between"> <div className="p-4 h-full flex flex-col justify-between">
@ -191,7 +193,7 @@ export default function IndeksCarouselComponent(props: {
</p> </p>
</div> </div>
</div> </div>
</div> </Link>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>

View File

@ -23,6 +23,7 @@ export default function FilterVideoComponent(props: {
startDateString?: string; startDateString?: string;
endDateString?: string; endDateString?: string;
monthYearFilter?: any; monthYearFilter?: any;
isRegionalCall?: any;
}) { }) {
const { const {
categoryFilter, categoryFilter,
@ -30,6 +31,7 @@ export default function FilterVideoComponent(props: {
startDateString, startDateString,
endDateString, endDateString,
monthYearFilter, monthYearFilter,
isRegionalCall,
} = props; } = props;
const [newContent, setNewContent] = useState<any>(); const [newContent, setNewContent] = useState<any>();
const asPath = usePathname(); const asPath = usePathname();
@ -43,8 +45,7 @@ export default function FilterVideoComponent(props: {
const categorie = searchParams?.get("category"); const categorie = searchParams?.get("category");
const group = searchParams?.get("group"); const group = searchParams?.get("group");
const [totalContent, setTotalContent] = useState(); const [totalContent, setTotalContent] = useState();
const isRegional = isRegionalCall || group || asPath.includes("/polda/");
const isRegional = group || asPath.includes("/polda/");
const searchType = isRegional ? "regional" : "filter"; const searchType = isRegional ? "regional" : "filter";
const router = useRouter(); const router = useRouter();
const poldaName = params?.polda_name; const poldaName = params?.polda_name;
@ -54,7 +55,7 @@ export default function FilterVideoComponent(props: {
? `/polda/${poldaName}` ? `/polda/${poldaName}`
: satkerName : satkerName
? `/satker/${satkerName}` ? `/satker/${satkerName}`
: "/"; : "";
useEffect(() => { useEffect(() => {
if (searchType === "regional") { if (searchType === "regional") {
@ -78,10 +79,16 @@ export default function FilterVideoComponent(props: {
let endDateFilter = endDateString ? endDateString : ""; let endDateFilter = endDateString ? endDateString : "";
let monthFilter = monthYearFilter ? monthYearFilter : ""; let monthFilter = monthYearFilter ? monthYearFilter : "";
const search = title == undefined ? "" : title;
const filter =
categoryFilter?.length > 0
? categoryFilter?.sort().join(",")
: categorie || "";
const response = await listDataRegional( const response = await listDataRegional(
"2", "2",
"", search,
"", filter,
"", "",
"", "",
startDateFilter, startDateFilter,
@ -95,7 +102,8 @@ export default function FilterVideoComponent(props: {
const contentData = data?.content; const contentData = data?.content;
setNewContent(contentData); setNewContent(contentData);
setTotalData(data?.totalElements); setTotalData(data?.totalElements);
// setLoading(false); setTotalPage(data?.totalPages);
setTotalContent(data?.totalElements);
} }
async function getDataAll() { async function getDataAll() {
@ -152,10 +160,12 @@ export default function FilterVideoComponent(props: {
<CarouselContent> <CarouselContent>
{newContent?.map((video: any) => ( {newContent?.map((video: any) => (
<CarouselItem key={video?.id} className="md:basis-1/2 lg:basis-1/3"> <CarouselItem key={video?.id} className="md:basis-1/2 lg:basis-1/3">
<div <Link
onClick={() => href={`${prefixPath}${video?.slug}`}
router.push(prefixPath + `/video/detail/${video?.slug}`) // href={prefixPath + `/video/detail/${video?.slug}`}
} // onClick={() =>
// router.push(prefixPath + `/video/detail/${video?.slug}`)
// }
className="cursor-pointer relative group overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300" className="cursor-pointer relative group overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300"
> >
{/* Image with motion effect */} {/* Image with motion effect */}
@ -164,17 +174,19 @@ export default function FilterVideoComponent(props: {
// whileHover={{ scale: 0.95 }} // whileHover={{ scale: 0.95 }}
// transition={{ duration: 0.3 }} // transition={{ duration: 0.3 }}
> >
<Image {video?.thumbnailLink && (
priority={true} <Image
// placeholder={`data:image/svg+xml;base64,${toBase64( priority={true}
// shimmer(700, 475) // placeholder={`data:image/svg+xml;base64,${toBase64(
// )}`} // shimmer(700, 475)
alt="video" // )}`}
width={2560} alt="video"
height={1440} width={2560}
src={video?.smallThumbnailLink} height={1440}
className="w-full h-full object-cover" src={video?.thumbnailLink}
/> className="w-full h-full object-cover"
/>
)}
</div> </div>
{/* Badge category */} {/* Badge category */}
@ -216,7 +228,7 @@ export default function FilterVideoComponent(props: {
</p> </p>
*/} */}
</div> </div>
</div> </Link>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>

View File

@ -272,6 +272,47 @@ const DetailImage = (data: any) => {
// } // }
// }; // };
// const handleDownload = () => {
// if (downloadProgress !== 0) return;
// if (!imageSizeSelected) {
// alert("Please select an image size before downloading.");
// return;
// }
// if (!userId) {
// router.push("/auth");
// return;
// }
// sendActivityLog(2);
// sendActivityLog(3);
// if (isDownloadAll) {
// const baseId = slug.split("-")?.[0];
// const url = `${process.env.NEXT_PUBLIC_API}/media/file/download-zip?id=${baseId}&resolution=${imageSizeSelected}`;
// downloadFile(url, "FileDownload.zip");
// } else {
// const selectedFile = detailDataImage?.files?.[selectedImage];
// if (!selectedFile) {
// toast({
// description: "Gambar tidak ditemukan.",
// variant: "destructive",
// });
// return;
// }
// if (isFromSPIT && main?.url?.includes("spit.humas")) {
// // downloadFile(selectedFile.url, selectedFile.names || "image.jpg");
// downloadFile(`${main?.url}`, `${main.names}`);
// } else {
// const url = `${process.env.NEXT_PUBLIC_API}/media/view?id=${selectedFile.id}&operation=file&type=image&resolution=${imageSizeSelected}`;
// downloadFile(`${main?.url}`, `${main.names}`);
// }
// }
// };
const handleDownload = () => { const handleDownload = () => {
if (downloadProgress !== 0) return; if (downloadProgress !== 0) return;
@ -303,12 +344,16 @@ const DetailImage = (data: any) => {
return; return;
} }
if (isFromSPIT && main?.url?.includes("spit.humas")) { if (isFromSPIT && selectedFile?.url?.includes("spit.humas")) {
// downloadFile(selectedFile.url, selectedFile.names || "image.jpg"); // ambil url asli dari SPIT, tapi nama file dari judul (main.names)
downloadFile(`${main?.url}`, `${main.names}`); downloadFile(
selectedFile.url,
main?.names || detailDataImage?.title || "image"
);
} else { } else {
const url = `${process.env.NEXT_PUBLIC_API}/media/view?id=${selectedFile.id}&operation=file&type=image&resolution=${imageSizeSelected}`; const url = `${process.env.NEXT_PUBLIC_API}/media/view?id=${selectedFile.id}&operation=file&type=image&resolution=${imageSizeSelected}`;
downloadFile(`${main?.url}`, `${main.names}`); // ambil file sesuai yang dipilih, nama tetap dari judul (main.names)
downloadFile(url, main?.names || detailDataImage?.title || "image");
} }
} }
}; };

View File

@ -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);
} }