From 2f745162a27c65fcf81114e5a1f3a3415e3137dc Mon Sep 17 00:00:00 2001 From: Rama Priyanto Date: Thu, 2 Jan 2025 13:24:16 +0700 Subject: [PATCH 1/4] feat:approval --- components/form/content/image-detail-form.tsx | 164 +++++++++++++++--- 1 file changed, 138 insertions(+), 26 deletions(-) diff --git a/components/form/content/image-detail-form.tsx b/components/form/content/image-detail-form.tsx index b845b15f..11b40be2 100644 --- a/components/form/content/image-detail-form.tsx +++ b/components/form/content/image-detail-form.tsx @@ -43,7 +43,8 @@ import { DialogTitle, } from "@/components/ui/dialog"; import { Textarea } from "@/components/ui/textarea"; -import { error, loading } from "@/config/swal"; +import { close, error, loading } from "@/config/swal"; +import { te } from "date-fns/locale"; const imageSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -112,6 +113,7 @@ export default function FormImageDetail() { const [selectedPublishers, setSelectedPublishers] = useState([]); const [description, setDescription] = useState(""); const [main, setMain] = useState([]); + const [filePlacements, setFilePlacements] = useState([]); const [selectedTarget, setSelectedTarget] = useState(""); const [files, setFiles] = useState([]); @@ -190,6 +192,14 @@ export default function FormImageDetail() { } }; + const setupPlacementCheck = (length: number) => { + const temp = []; + for (let i = 0; i < length; i++) { + temp.push([]); + } + setFilePlacements(temp); + }; + useEffect(() => { async function initState() { if (id) { @@ -204,6 +214,7 @@ export default function FormImageDetail() { names: details?.files[0]?.fileName, format: details?.files[0]?.format, }); + setupPlacementCheck(details?.files?.length); if (details.publishedForObject) { const publisherIds = details.publishedForObject.map( @@ -227,9 +238,16 @@ export default function FormImageDetail() { }, [refresh, setValue]); const actionApproval = (e: string) => { + const temp = []; + for (const element of detail.files) { + temp.push([]); + } + setFilePlacements(temp); setStatus(e); - setModalOpen(true); + setFiles(detail.files); + setDescription(""); + setModalOpen(true); }; const submit = async () => { @@ -238,31 +256,44 @@ export default function FormImageDetail() { Number(status) == 2 || Number(status) == 4 ) { - MySwal.fire({ - title: "Simpan Approval", - text: "", - icon: "warning", - showCancelButton: true, - cancelButtonColor: "#d33", - confirmButtonColor: "#3085d6", - confirmButtonText: "Simpan", - }).then((result) => { - if (result.isConfirmed) { - save(); - } - }); + save(); + + // MySwal.fire({ + // title: "Simpan Approval", + // text: "", + // icon: "warning", + // showCancelButton: true, + // cancelButtonColor: "#d33", + // confirmButtonColor: "#3085d6", + // confirmButtonText: "Simpan", + // }).then((result) => { + // if (result.isConfirmed) { + // save(); + // } + // }); } }; + const getPlacement = () => { + console.log("getPlaa", filePlacements); + const temp = []; + for (let i = 0; i < filePlacements?.length; i++) { + if (filePlacements[i].length !== 0) { + const now = filePlacements[i].filter((a) => a !== "all"); + const data = { mediaFileId: files[i].id, placement: now.join(",") }; + temp.push(data); + } + } + return temp; + }; + async function save() { const data = { mediaUploadId: id, statusId: status, message: description, - files: [], - // files: isMabesApprover ? getPlacement() : [], + files: isMabesApprover ? getPlacement() : [], }; - loading(); const response = await submitApproval(data); @@ -275,6 +306,8 @@ export default function FormImageDetail() { listFiles: rejectedFiles, }; + console.log("reject", dataReject); + const resReject = await rejectFiles(dataReject); if (resReject?.error) { @@ -286,6 +319,38 @@ export default function FormImageDetail() { return false; } + const setupPlacement = ( + index: number, + placement: string, + checked: boolean + ) => { + let temp = [...filePlacements]; + if (checked) { + if (placement === "all") { + temp[index] = ["all", "mabes", "polda", "international"]; + } else { + const now = temp[index]; + now.push(placement); + if (now.length === 3 && !now.includes("all")) { + now.push("all"); + } + temp[index] = now; + } + } else { + if (placement === "all") { + temp[index] = []; + } else { + const now = temp[index].filter((a) => a !== placement); + console.log("now", now); + temp[index] = now; + if (now.length === 3 && now.includes("all")) { + const newData = now.filter((b) => b !== "all"); + temp[index] = newData; + } + } + } + setFilePlacements(temp); + }; function handleDeleteFileApproval(id: number) { const selectedFiles = files.filter((file) => file.id != id); @@ -606,7 +671,7 @@ export default function FormImageDetail() { Berikan Komentar {status == "2" - ? files?.map((file) => ( + ? files?.map((file, index) => (
- + + setupPlacement(index, "all", Boolean(e)) + } + />
- + + setupPlacement(index, "mabes", Boolean(e)) + } + />
- + + setupPlacement(index, "polda", Boolean(e)) + } + />
diff --git a/app/[locale]/(protected)/contributor/content/teks/components/columns.tsx b/app/[locale]/(protected)/contributor/content/teks/components/columns.tsx index 4984ce42..3e3af62b 100644 --- a/app/[locale]/(protected)/contributor/content/teks/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/content/teks/components/columns.tsx @@ -12,6 +12,7 @@ import { import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { format } from "date-fns"; +import { Link } from "@/components/navigation"; const columns: ColumnDef[] = [ { @@ -139,12 +140,18 @@ const columns: ColumnDef[] = [ - + View - + + + + + Edit + + Delete diff --git a/app/[locale]/(protected)/contributor/content/teks/create/page.tsx b/app/[locale]/(protected)/contributor/content/teks/create/page.tsx new file mode 100644 index 00000000..45dcac20 --- /dev/null +++ b/app/[locale]/(protected)/contributor/content/teks/create/page.tsx @@ -0,0 +1,16 @@ +import FormAudio from "@/components/form/content/audio-form"; +import FormTeks from "@/components/form/content/teks-form"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; + +const TeksCreatePage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default TeksCreatePage; diff --git a/app/[locale]/(protected)/contributor/content/teks/detail/[id]/page.tsx b/app/[locale]/(protected)/contributor/content/teks/detail/[id]/page.tsx new file mode 100644 index 00000000..1245c0a1 --- /dev/null +++ b/app/[locale]/(protected)/contributor/content/teks/detail/[id]/page.tsx @@ -0,0 +1,16 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormImageDetail from "@/components/form/content/image-detail-form"; +import FormTeksDetail from "@/components/form/content/teks-detail-form"; + +const TeksDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default TeksDetailPage; diff --git a/app/[locale]/(protected)/contributor/content/teks/page.tsx b/app/[locale]/(protected)/contributor/content/teks/page.tsx index 9ffeb14b..a352d007 100644 --- a/app/[locale]/(protected)/contributor/content/teks/page.tsx +++ b/app/[locale]/(protected)/contributor/content/teks/page.tsx @@ -6,6 +6,7 @@ import { Newspaper, NewspaperIcon, UploadIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Icon } from "@iconify/react/dist/iconify.js"; import TableTeks from "./components/table-teks"; +import { Link } from "@/components/navigation"; const ReactTableTeksPage = () => { return ( @@ -56,15 +57,18 @@ const ReactTableTeksPage = () => {
Konten Teks
+
- - + + {/* + */}
diff --git a/app/[locale]/(protected)/contributor/content/teks/update/[id]/page.tsx b/app/[locale]/(protected)/contributor/content/teks/update/[id]/page.tsx new file mode 100644 index 00000000..c7b8dfec --- /dev/null +++ b/app/[locale]/(protected)/contributor/content/teks/update/[id]/page.tsx @@ -0,0 +1,17 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormImageDetail from "@/components/form/content/image-detail-form"; +import FormImageUpdate from "@/components/form/content/image-update-form"; +import FormTeksUpdate from "@/components/form/content/teks-update-form"; + +const TeksUpdatePage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default TeksUpdatePage; diff --git a/app/[locale]/(protected)/contributor/content/video/components/columns.tsx b/app/[locale]/(protected)/contributor/content/video/components/columns.tsx index 4984ce42..b58dd079 100644 --- a/app/[locale]/(protected)/contributor/content/video/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/content/video/components/columns.tsx @@ -12,6 +12,7 @@ import { import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { format } from "date-fns"; +import { Link } from "@/components/navigation"; const columns: ColumnDef[] = [ { @@ -139,12 +140,18 @@ const columns: ColumnDef[] = [ - + View - + + + + + Edit + + Delete diff --git a/app/[locale]/(protected)/contributor/content/video/detail/[id]/page.tsx b/app/[locale]/(protected)/contributor/content/video/detail/[id]/page.tsx new file mode 100644 index 00000000..377c0a87 --- /dev/null +++ b/app/[locale]/(protected)/contributor/content/video/detail/[id]/page.tsx @@ -0,0 +1,16 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormImageDetail from "@/components/form/content/image-detail-form"; +import FormVideoDetail from "@/components/form/content/video-detail-form"; + +const VideoDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default VideoDetailPage; diff --git a/app/[locale]/(protected)/contributor/content/video/page.tsx b/app/[locale]/(protected)/contributor/content/video/page.tsx index 264adef7..d3202058 100644 --- a/app/[locale]/(protected)/contributor/content/video/page.tsx +++ b/app/[locale]/(protected)/contributor/content/video/page.tsx @@ -58,16 +58,16 @@ const ReactTableVideoPage = () => { Konten Video
- + - + */}
diff --git a/app/[locale]/(protected)/contributor/content/video/update/[id]/page.tsx b/app/[locale]/(protected)/contributor/content/video/update/[id]/page.tsx new file mode 100644 index 00000000..1b0a481c --- /dev/null +++ b/app/[locale]/(protected)/contributor/content/video/update/[id]/page.tsx @@ -0,0 +1,17 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormImageDetail from "@/components/form/content/image-detail-form"; +import FormImageUpdate from "@/components/form/content/image-update-form"; +import FormVideoUpdate from "@/components/form/content/video-update-form"; + +const VideoUpdatePage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default VideoUpdatePage; diff --git a/components/form/content/audio-form.tsx b/components/form/content/audio-form.tsx new file mode 100644 index 00000000..02540647 --- /dev/null +++ b/components/form/content/audio-form.tsx @@ -0,0 +1,1021 @@ +"use client"; +import React, { + ChangeEvent, + useEffect, + useRef, + Fragment, + useState, +} from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import { Upload } from "tus-js-client"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { redirect, useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Checkbox } from "@/components/ui/checkbox"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import JoditEditor from "jodit-react"; +import { register } from "module"; +import { Switch } from "@/components/ui/switch"; +import Cookies from "js-cookie"; +import { + createMedia, + getTagsBySubCategoryId, + listEnableCategory, + uploadThumbnail, +} from "@/service/content/content"; +import { uploadThumbnailBlog } from "@/service/blog/blog"; +import { Textarea } from "@/components/ui/textarea"; +import { + generateDataArticle, + getDetailArticle, + getGenerateKeywords, + getGenerateTitle, +} from "@/service/content/ai"; +import { getCookiesDecrypt } from "@/lib/utils"; +import { useDropzone } from "react-dropzone"; +import { Icon } from "@iconify/react"; +import { CloudUpload } from "lucide-react"; +import Image from "next/image"; +import { error, loading } from "@/config/swal"; +import { Item } from "@radix-ui/react-dropdown-menu"; + +const imageSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + description: z + .string() + .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), + creatorName: z.string().min(1, { message: "Creator diperlukan" }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +interface FileWithPreview extends File { + preview: string; +} + +type Category = { + id: string; + name: string; +}; + +export default function FormAudio() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type ImageSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + const roleId = getCookiesDecrypt("urie"); + + const [categories, setCategories] = useState([]); + const [selectedCategory, setSelectedCategory] = useState(); + const [tags, setTags] = useState([]); + const [thumbnail, setThumbnail] = useState(null); + const [preview, setPreview] = useState(null); + const [selectedLanguage, setSelectedLanguage] = useState(""); + + const [selectedSEO, setSelectedSEO] = useState(""); + const [title, setTitle] = useState(""); + const [selectedAdvConfig, setSelectedAdvConfig] = useState(""); + const [editingArticleId, setEditingArticleId] = useState(null); + const [isLoading, setIsLoading] = useState(false); + + const [articleIds, setArticleIds] = useState([]); + const [isGeneratedArticle, setIsGeneratedArticle] = useState(false); + const [articleBody, setArticleBody] = useState(""); + const [selectedArticleId, setSelectedArticleId] = useState( + null + ); + const [selectedMainKeyword, setSelectedMainKeyword] = useState(""); + const [selectedWritingStyle, setSelectedWritingStyle] = useState(""); + const [selectedSize, setSelectedSize] = useState(""); + const [detailData, setDetailData] = useState(null); + const [articleImages, setArticleImages] = useState([]); + const [isSwitchOn, setIsSwitchOn] = useState(false); + + const [selectedTarget, setSelectedTarget] = useState(""); + const [unitSelection, setUnitSelection] = useState({ + allUnit: false, + mabes: false, + polda: false, + polres: false, + }); + + let fileTypeId = "4"; + let progressInfo: any = []; + let counterUpdateProgress = 0; + const [progressList, setProgressList] = useState([]); + let uploadPersen = 0; + const [isStartUpload, setIsStartUpload] = useState(false); + const [counterProgress, setCounterProgress] = useState(0); + + const [files, setFiles] = useState([]); + + const { getRootProps, getInputProps } = useDropzone({ + onDrop: (acceptedFiles) => { + setFiles(acceptedFiles.map((file) => Object.assign(file))); + }, + }); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(imageSchema), + }); + + const doGenerateMainKeyword = async () => { + console.log(selectedMainKeyword); + if (selectedMainKeyword?.length > 1) { + try { + setIsLoading(true); + const titleData = { + keyword: selectedMainKeyword, + style: selectedWritingStyle, + website: "0", + connectToWeb: true, + lang: selectedLanguage, + pointOfView: "None", + clientId: "", + }; + console.log("Sending request for title with data:", titleData); + const titleRes = await getGenerateTitle(titleData); + setTitle(titleRes?.data?.data || ""); + console.log("Generated title:", titleRes?.data?.data); + + const keywordsData = { + keyword: selectedMainKeyword, + style: selectedWritingStyle, + website: "0", + connectToWeb: true, + lang: selectedLanguage, + pointOfView: "None", + clientId: "", + }; + console.log("Sending request for keywords with data:", keywordsData); + const keywordsRes = await getGenerateKeywords(keywordsData); + setSelectedSEO(keywordsRes?.data?.data || []); + console.log("Generated keywords:", keywordsRes?.data?.data); + } catch (error) { + console.error("Error during generation process:", error); + } finally { + setIsLoading(false); + } + } else { + console.error("Please provide a valid main keyword."); + } + }; + + const doGenerateTitle = async () => { + if (selectedMainKeyword?.length > 1) { + try { + setIsLoading(true); + const titleData = { + keyword: selectedMainKeyword, + style: selectedWritingStyle, + website: "0", + connectToWeb: true, + lang: selectedLanguage, + pointOfView: "None", + clientId: "", + }; + console.log("Sending request for title with data:", titleData); + const titleRes = await getGenerateTitle(titleData); + setTitle(titleRes?.data?.data || ""); + console.log("Generated title:", titleRes?.data?.data); + } catch (error) { + console.error("Error generating title:", error); + } finally { + setIsLoading(false); + } + } else { + console.error("Please provide a valid main keyword."); + } + }; + + const doGenerateKeyword = async () => { + if (selectedMainKeyword?.length > 1) { + try { + setIsLoading(true); + const keywordsData = { + keyword: selectedMainKeyword, + style: selectedWritingStyle, + website: "0", + connectToWeb: true, + lang: selectedLanguage, + pointOfView: "None", + clientId: "", + }; + console.log("Sending request for keywords with data:", keywordsData); + const keywordsRes = await getGenerateKeywords(keywordsData); + setSelectedSEO(keywordsRes?.data?.data || []); + console.log("Generated keywords:", keywordsRes?.data?.data); + } catch (error) { + console.error("Error generating keywords:", error); + } finally { + setIsLoading(false); + } + } else { + console.error("Please provide a valid main keyword."); + } + }; + + const handleGenerateArtikel = async () => { + const request = { + advConfig: selectedAdvConfig, + style: selectedWritingStyle, + website: "None", + connectToWeb: true, + lang: selectedLanguage, + pointOfView: "None", + title: title, + imageSource: "Web", + mainKeyword: selectedMainKeyword, + additionalKeywords: selectedSEO, + targetCountry: null, + articleSize: selectedSize, + projectId: 2, + createdBy: roleId, + clientId: "ngDLPPiorplznw2jTqVe3YFCz5xqKfUJ", + }; + + const res = await generateDataArticle(request); + close(); + + if (res.error) { + console.error(res.message); + return false; + } + + const newArticleId = res?.data?.data?.id; + setIsGeneratedArticle(true); + + setArticleIds((prevIds: string[]) => { + if (prevIds.length < 5) { + return [...prevIds, newArticleId]; + } else { + const updatedIds = [...prevIds]; + updatedIds[4] = newArticleId; + return updatedIds; + } + }); + + Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds)); + }; + + const handleArticleIdClick = async (id: string) => { + const res = await getDetailArticle(id); + const articleData = res?.data?.data; + + const cleanArticleBody = articleData?.articleBody?.replace( + /]*>/g, + "" + ); + const articleImagesData = articleData?.imagesUrl?.split(","); + + setArticleBody(cleanArticleBody || ""); + setDetailData(articleData); + setSelectedArticleId(id); + setArticleImages(articleImagesData || []); + }; + + const handleAddTag = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && e.currentTarget.value.trim()) { + e.preventDefault(); + const newTag = e.currentTarget.value.trim(); + if (!tags.includes(newTag)) { + setTags((prevTags) => [...prevTags, newTag]); // Add new tag + // setValue("tags", ""); // Clear input field + } + } + }; + + const handleRemoveTag = (index: number) => { + setTags((prevTags) => prevTags.filter((_, i) => i !== index)); // Remove tag + }; + + const handleRemoveImage = (index: number) => { + setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index)); + }; + + useEffect(() => { + async function initState() { + getCategories(); + // setVideoActive(fileTypeId == '2'); + // getRoles(); + } + + initState(); + }, []); + + const getCategories = async () => { + try { + const category = await listEnableCategory(fileTypeId); + const resCategory: Category[] = category.data.data.content; + + setCategories(resCategory); + console.log("data category", resCategory); + + if (scheduleId && scheduleType === "3") { + const findCategory = resCategory.find((o) => + o.name.toLowerCase().includes("pers rilis") + ); + + if (findCategory) { + // setValue("categoryId", findCategory.id); + setSelectedCategory(findCategory.id); // Set the selected category + const response = await getTagsBySubCategoryId(findCategory.id); + setTags(response?.data.data); + } + } + } catch (error) { + console.error("Failed to fetch categories:", error); + } + }; + + const save = async (data: ImageSchema) => { + loading(); + const finalTags = tags.join(", "); + const finalTitle = isSwitchOn ? title : data.title; + const requestData = { + ...data, + title: finalTitle, + description: data.description, + htmlDescription: data.description, + fileTypeId, + categoryId: selectedCategory, + subCategoryId: selectedCategory, + uploadedBy: "2b7c8d83-d298-4b19-9f74-b07924506b58", + statusId: "1", + publishedFor: "6", + creatorName: data.creatorName, + tags: finalTags, + isYoutube: false, + isInternationalMedia: false, + }; + + let id = Cookies.get("idCreate"); + + if (id == undefined) { + const response = await createMedia(requestData); + console.log("Form Data Submitted:", requestData); + + if (response?.error) { + MySwal.fire("Error", response?.message, "error"); + return; + } + Cookies.set("idCreate", response?.data.data, { expires: 1 }); + id = response?.data?.data; + + // Upload Thumbnail + const formMedia = new FormData(); + console.log("Thumbnail : ", files[0]); + formMedia.append("file", files[0]); + const responseThumbnail = await uploadThumbnail(id, formMedia); + if (responseThumbnail?.error == true) { + error(responseThumbnail?.message); + return false; + } + } + + // Upload File + const progressInfoArr = []; + for (const item of files) { + progressInfoArr.push({ percentage: 0, fileName: item.name }); + } + progressInfo = progressInfoArr; + setIsStartUpload(true); + setProgressList(progressInfoArr); + + close(); + // showProgress(); + files.map(async (item: any, index: number) => { + await uploadResumableFile( + index, + String(id), + item, + fileTypeId == "2" || fileTypeId == "4" ? item.duration : "0" + ); + }); + + Cookies.remove("idCreate"); + + // MySwal.fire("Sukses", "Data berhasil disimpan.", "success"); + }; + + const onSubmit = (data: ImageSchema) => { + MySwal.fire({ + title: "Simpan Data", + text: "Apakah Anda yakin ingin menyimpan data ini?", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + }; + + async function uploadResumableFile( + idx: number, + id: string, + file: any, + duration: string + ) { + console.log(idx, id, file, duration); + + // const placements = getPlacement(file.placements); + // console.log("Placementttt: : ", placements); + + const upload = new Upload(file, { + endpoint: `${process.env.NEXT_PUBLIC_API}/media/file/upload`, + retryDelays: [0, 3000, 6000, 12_000, 24_000], + chunkSize: 20_000, + metadata: { + mediaid: id, + filename: file.name, + filetype: file.type, + duration, + isWatermark: "true", // hardcode + }, + onError: async (e: any) => { + console.log("Error upload :", e); + error(e); + }, + onChunkComplete: ( + chunkSize: any, + bytesAccepted: any, + bytesTotal: any + ) => { + const uploadPersen = Math.floor((bytesAccepted / bytesTotal) * 100); + progressInfo[idx].percentage = uploadPersen; + counterUpdateProgress++; + console.log(counterUpdateProgress); + setProgressList(progressInfo); + setCounterProgress(counterUpdateProgress); + }, + onSuccess: async () => { + uploadPersen = 100; + progressInfo[idx].percentage = 100; + counterUpdateProgress++; + setCounterProgress(counterUpdateProgress); + successTodo(); + }, + }); + + upload.start(); + } + + const successSubmit = (redirect: string) => { + MySwal.fire({ + title: "Sukses", + text: "Data berhasil disimpan.", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then(() => { + router.push(redirect); + }); + }; + + function successTodo() { + let counter = 0; + for (const element of progressInfo) { + if (element.percentage == 100) { + counter++; + } + } + if (counter == progressInfo.length) { + setIsStartUpload(false); + // hideProgress(); + Cookies.remove("idCreate"); + successSubmit("/in/contributor/content/audio/"); + } + } + + const handleImageChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (file) { + setThumbnail(file); + console.log("Selected Thumbnail:", file); + } + if (file) { + setPreview(URL.createObjectURL(file)); + } + }; + + const renderFilePreview = (file: FileWithPreview) => { + if (file.type.startsWith("image")) { + return ( + {file.name} + ); + } else { + return ; + } + }; + + const handleRemoveFile = (file: FileWithPreview) => { + const uploadedFiles = files; + const filtered = uploadedFiles.filter((i) => i.name !== file.name); + setFiles([...filtered]); + }; + + const fileList = files.map((file) => ( +
+
+
{renderFilePreview(file)}
+
+
{file.name}
+
+ {Math.round(file.size / 100) / 10 > 1000 ? ( + <>{(Math.round(file.size / 100) / 10000).toFixed(1)} + ) : ( + <>{(Math.round(file.size / 100) / 10).toFixed(1)} + )} + {" kb"} +
+
+
+ + +
+ )); + + const handleRemoveAllFiles = () => { + setFiles([]); + }; + + return ( +
+
+ +
+

Form Konten Audio

+
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.title?.message && ( +

{errors.title.message}

+ )} +
+ +
+
+ + +
+
+
+ +
+ + setIsSwitchOn(checked) + } + /> +
+
+ {isSwitchOn && ( +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ setSelectedMainKeyword(e.target.value)} + placeholder="Enter Main Keyword" + /> + {/* )} + /> */} +
+
+
+
+ + +
+
+ setTitle(e.target.value)} + placeholder="Generated Title" + /> +
+
+
+
+ + +
+

+ Kata kunci untuk disertakan dalam teks +

+

+ JIka Anda tidak Memberikan kata kunci, kami akan secara + otomatis membuat kata kunci yang relevan dari kata kunci + utama untuk setiap bagian dan menggunakannya untuk membuat + artikel. Untuk menambahkan kata kunci baru, ketik ', + + kata kunci'. +

+
+