From f3120e4cf8ad42184204babb01fb21113cc61a43 Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Wed, 30 Apr 2025 01:16:33 +0800 Subject: [PATCH] feat:update landing,kurator --- .../task-ta/components/columns.tsx | 13 +- .../(protected)/contributor/task-ta/page.tsx | 21 +- .../contributor/task-ta/upload-task/page.tsx | 17 + .../(public)/image/detail/[slug]/page.tsx | 5 +- app/[locale]/(public)/image/filter/page.tsx | 5 +- components/form/blog/blog--update-form.tsx | 2 +- components/form/blog/blog-form.tsx | 2 +- components/form/content/audio-update-form.tsx | 2 +- components/form/content/audio-update-seo.tsx | 2 +- components/form/content/image-form.tsx | 2 +- components/form/content/image-update-form.tsx | 2 +- components/form/content/image-update-seo.tsx | 2 +- components/form/content/teks-update-form.tsx | 2 +- components/form/content/teks-update-seo.tsx | 2 +- components/form/planning/mediahub-publish.tsx | 2 +- components/form/planning/medsos-publish.tsx | 2 +- components/form/task-ta/task-ta-form.tsx | 2 +- components/form/task-ta/task-ta-new.tsx | 945 ++++++++++++++++++ components/form/task/task-edit-form.tsx | 6 +- components/landing-page/hero.tsx | 4 +- components/landing-page/navbar.tsx | 10 +- components/partials/auth/login-form.tsx | 5 +- lib/menus.ts | 34 +- 23 files changed, 1039 insertions(+), 50 deletions(-) create mode 100644 app/[locale]/(protected)/contributor/task-ta/upload-task/page.tsx create mode 100644 components/form/task-ta/task-ta-new.tsx diff --git a/app/[locale]/(protected)/contributor/task-ta/components/columns.tsx b/app/[locale]/(protected)/contributor/task-ta/components/columns.tsx index c05d82f0..0a49cdda 100644 --- a/app/[locale]/(protected)/contributor/task-ta/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/task-ta/components/columns.tsx @@ -1,8 +1,8 @@ import * as React from "react"; import { ColumnDef } from "@tanstack/react-table"; -import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react"; -import { cn } from "@/lib/utils"; +import { Eye, MoreVertical, SquarePen, Trash2, Upload } from "lucide-react"; +import { cn, getCookiesDecrypt } from "@/lib/utils"; import { DropdownMenu, DropdownMenuContent, @@ -105,6 +105,7 @@ const useTableColumns = () => { cell: ({ row }) => { const router = useRouter(); const MySwal = withReactContent(Swal); + const roleId = Number(getCookiesDecrypt("urie")) || 0; async function deleteProcess(id: any) { loading(); @@ -170,6 +171,14 @@ const useTableColumns = () => { Edit + {roleId == 12 && ( + + + + Upload Tugas + + + )} TaskDelete(row.original.id)} className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none" diff --git a/app/[locale]/(protected)/contributor/task-ta/page.tsx b/app/[locale]/(protected)/contributor/task-ta/page.tsx index 7873633d..b1b9a4c5 100644 --- a/app/[locale]/(protected)/contributor/task-ta/page.tsx +++ b/app/[locale]/(protected)/contributor/task-ta/page.tsx @@ -5,7 +5,11 @@ import { Button } from "@/components/ui/button"; import { UploadIcon } from "lucide-react"; import SiteBreadcrumb from "@/components/site-breadcrumb"; import { Link } from "@/components/navigation"; -import { checkAuthorization, checkLoginSession } from "@/lib/utils"; +import { + checkAuthorization, + checkLoginSession, + getCookiesDecrypt, +} from "@/lib/utils"; import React, { useEffect } from "react"; import { useTranslations } from "next-intl"; import TaskTaTable from "./components/task-ta-table"; @@ -20,6 +24,7 @@ const TaskTaPage = () => { initState(); }, []); + const roleId = Number(getCookiesDecrypt("urie")) || 0; return (
@@ -33,12 +38,14 @@ const TaskTaPage = () => { {t("tabel")} {t("task-ta")}
- - - + {roleId !== 12 && ( + + + + )}
diff --git a/app/[locale]/(protected)/contributor/task-ta/upload-task/page.tsx b/app/[locale]/(protected)/contributor/task-ta/upload-task/page.tsx new file mode 100644 index 00000000..96600bfe --- /dev/null +++ b/app/[locale]/(protected)/contributor/task-ta/upload-task/page.tsx @@ -0,0 +1,17 @@ +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormTaskTa from "@/components/form/task-ta/task-ta-form"; +import FormTaskTaNew from "@/components/form/task-ta/task-ta-new"; + +const TaskTaUploadPage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default TaskTaUploadPage; diff --git a/app/[locale]/(public)/image/detail/[slug]/page.tsx b/app/[locale]/(public)/image/detail/[slug]/page.tsx index 44e9748c..383fd0d0 100644 --- a/app/[locale]/(public)/image/detail/[slug]/page.tsx +++ b/app/[locale]/(public)/image/detail/[slug]/page.tsx @@ -582,7 +582,10 @@ const DetailInfo = () => { {formatDateToIndonesian( new Date(detailDataImage?.updatedAt) )}{" "} - {"WIB"} + {detailDataImage?.timezone + ? detailDataImage?.timezone + : "WIB"} +  

 |  diff --git a/app/[locale]/(public)/image/filter/page.tsx b/app/[locale]/(public)/image/filter/page.tsx index 51f6e492..4e5750a0 100644 --- a/app/[locale]/(public)/image/filter/page.tsx +++ b/app/[locale]/(public)/image/filter/page.tsx @@ -698,11 +698,12 @@ const FilterPage = () => { }} /> -

+
{formatDateToIndonesian( new Date(image?.createdAt) )}{" "} - {image?.timezone ? image?.timezone : "WIB"}|{" "} + {image?.timezone ? image?.timezone : "WIB"} +   | { - router.push("/en/contributor/blog"); + router.push("/in/contributor/blog"); }); }; diff --git a/components/form/blog/blog-form.tsx b/components/form/blog/blog-form.tsx index c6fffaee..155a6450 100644 --- a/components/form/blog/blog-form.tsx +++ b/components/form/blog/blog-form.tsx @@ -214,7 +214,7 @@ export default function FormBlog() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/en/contributor/blog"); + router.push("/in/contributor/blog"); }); }; diff --git a/components/form/content/audio-update-form.tsx b/components/form/content/audio-update-form.tsx index 20af4402..7ffd0630 100644 --- a/components/form/content/audio-update-form.tsx +++ b/components/form/content/audio-update-form.tsx @@ -344,7 +344,7 @@ export default function FormAudioUpdate() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/en/contributor/content/audio"); + router.push("/in/contributor/content/audio"); }); }; diff --git a/components/form/content/audio-update-seo.tsx b/components/form/content/audio-update-seo.tsx index 6c808570..ec007652 100644 --- a/components/form/content/audio-update-seo.tsx +++ b/components/form/content/audio-update-seo.tsx @@ -401,7 +401,7 @@ export default function FormAudioSeo() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/en/contributor/content/image"); + router.push("/in/contributor/content/image"); }); }; diff --git a/components/form/content/image-form.tsx b/components/form/content/image-form.tsx index aa70a5d4..4e255e53 100644 --- a/components/form/content/image-form.tsx +++ b/components/form/content/image-form.tsx @@ -631,7 +631,7 @@ export default function FormImage() { setIsStartUpload(false); // hideProgress(); Cookies.remove("idCreate"); - successSubmit("/in/contributor/content/image/"); + successSubmit("in/contributor/content/image/"); } } diff --git a/components/form/content/image-update-form.tsx b/components/form/content/image-update-form.tsx index 13be118b..cc0a1a50 100644 --- a/components/form/content/image-update-form.tsx +++ b/components/form/content/image-update-form.tsx @@ -373,7 +373,7 @@ export default function FormImageUpdate() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/en/contributor/content/image"); + router.push("/in/contributor/content/image"); }); }; diff --git a/components/form/content/image-update-seo.tsx b/components/form/content/image-update-seo.tsx index da3bebb3..0e7ea12e 100644 --- a/components/form/content/image-update-seo.tsx +++ b/components/form/content/image-update-seo.tsx @@ -401,7 +401,7 @@ export default function FormImageSeo() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/en/contributor/content/image"); + router.push("/in/contributor/content/image"); }); }; diff --git a/components/form/content/teks-update-form.tsx b/components/form/content/teks-update-form.tsx index 77b7c0aa..ee14e380 100644 --- a/components/form/content/teks-update-form.tsx +++ b/components/form/content/teks-update-form.tsx @@ -337,7 +337,7 @@ export default function FormTeksUpdate() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/en/contributor/content/teks"); + router.push("/in/contributor/content/teks"); }); }; diff --git a/components/form/content/teks-update-seo.tsx b/components/form/content/teks-update-seo.tsx index 633d60f8..488354f5 100644 --- a/components/form/content/teks-update-seo.tsx +++ b/components/form/content/teks-update-seo.tsx @@ -401,7 +401,7 @@ export default function FormTeksSeo() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/en/contributor/content/image"); + router.push("/in/contributor/content/image"); }); }; diff --git a/components/form/planning/mediahub-publish.tsx b/components/form/planning/mediahub-publish.tsx index d973236e..2af44c96 100644 --- a/components/form/planning/mediahub-publish.tsx +++ b/components/form/planning/mediahub-publish.tsx @@ -284,7 +284,7 @@ export default function PublishMediahub() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/en/contributor/planning/mediahub"); + router.push("/in/contributor/planning/mediahub"); }); }; diff --git a/components/form/planning/medsos-publish.tsx b/components/form/planning/medsos-publish.tsx index 76420e47..9b470a5a 100644 --- a/components/form/planning/medsos-publish.tsx +++ b/components/form/planning/medsos-publish.tsx @@ -277,7 +277,7 @@ export default function PublishMedsos() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/en/contributor/planning/medsos-mediahub"); + router.push("/in/contributor/planning/medsos-mediahub"); }); }; diff --git a/components/form/task-ta/task-ta-form.tsx b/components/form/task-ta/task-ta-form.tsx index 5d694a27..3005e8a7 100644 --- a/components/form/task-ta/task-ta-form.tsx +++ b/components/form/task-ta/task-ta-form.tsx @@ -548,7 +548,7 @@ export default function FormTaskTa() { isAudioUploadFinish && isTextUploadFinish ) { - successSubmit("/in/contributor/task"); + successSubmit("/in/contributor/task-ta"); } } diff --git a/components/form/task-ta/task-ta-new.tsx b/components/form/task-ta/task-ta-new.tsx new file mode 100644 index 00000000..ee649606 --- /dev/null +++ b/components/form/task-ta/task-ta-new.tsx @@ -0,0 +1,945 @@ +"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"; +import { data } from "jquery"; +import { options } from "@fullcalendar/core/preact.js"; +import dynamic from "next/dynamic"; +import { getCsrfToken } from "@/service/auth"; +import { Link } from "@/i18n/routing"; +import { request } from "http"; +import { useTranslations } from "next-intl"; + +interface FileWithPreview extends File { + preview: string; +} + +type Category = { + id: string; + name: string; +}; + +type Option = { + id: string; + label: string; +}; + +const CustomEditor = dynamic( + () => { + return import("@/components/editor/custom-editor"); + }, + { ssr: false } +); + +export default function FormTaskTaNew() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type ImageSchema = z.infer; + + const t = useTranslations("Form"); + 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 [isLoadingData, setIsLoadingData] = 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 inputRef = useRef(null); + + const [content, setContent] = useState(""); + + const [selectedTarget, setSelectedTarget] = useState(""); + const [unitSelection, setUnitSelection] = useState({ + allUnit: false, + mabes: false, + polda: false, + polres: false, + }); + + let fileTypeId = "1"; + 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 [filesTemp, setFilesTemp] = useState([]); + const [publishedFor, setPublishedFor] = useState([]); + + const options: Option[] = [ + { id: "all", label: "SEMUA" }, + { id: "5", label: "UMUM" }, + { id: "6", label: "JOURNALIS" }, + { id: "7", label: "POLRI" }, + { id: "8", label: "KSP" }, + ]; + + const { getRootProps, getInputProps } = useDropzone({ + onDrop: (acceptedFiles) => { + setFiles(acceptedFiles.map((file) => Object.assign(file))); + }, + }); + + 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." }) + .or( + z.literal(articleBody || "").refine((val) => val.length > 0, { + message: "Deskripsi diperlukan.", + }) + ), + creatorName: z.string().min(1, { message: "Creator diperlukan" }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), + }); + + const { + control, + handleSubmit, + getValues, + 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 < 3) { + return [...prevIds, newArticleId]; + } else { + const updatedIds = [...prevIds]; + updatedIds[2] = newArticleId; + return updatedIds; + } + }); + + Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds)); + }; + + const handleArticleIdClick = async (id: string) => { + setIsLoadingData(true); + let retryCount = 0; + const maxRetries = 20; + + try { + const waitForStatusUpdate = async () => { + while (retryCount < maxRetries) { + const res = await getDetailArticle(id); + const articleData = res?.data?.data; + + if (articleData?.status === 2) { + return articleData; + } + + retryCount++; + await new Promise((resolve) => setTimeout(resolve, 5000)); + } + + throw new Error("Timeout: Artikel belum selesai diproses."); + }; + const articleData = await waitForStatusUpdate(); + const cleanArticleBody = articleData?.articleBody?.replace( + /]*>/g, + "" + ); + const articleImagesData = articleData?.imagesUrl?.split(","); + setArticleBody(cleanArticleBody || ""); + setDetailData(articleData); + setSelectedArticleId(id); + setArticleImages(articleImagesData || []); + } catch (error) { + console.error("Error fetching article details:", error); + } finally { + setIsLoadingData(false); + } + }; + + 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 + if (inputRef.current) { + inputRef.current.value = ""; // 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 handleCheckboxChange = (id: string): void => { + if (id === "all") { + if (publishedFor.includes("all")) { + // Uncheck all checkboxes + setPublishedFor([]); + } else { + // Select all checkboxes + setPublishedFor( + options + .filter((opt: any) => opt.id !== "all") + .map((opt: any) => opt.id) + ); + } + } else { + const updatedPublishedFor = publishedFor.includes(id) + ? publishedFor.filter((item) => item !== id) + : [...publishedFor, id]; + + // Remove "all" if any checkbox is unchecked + if (publishedFor.includes("all") && id !== "all") { + setPublishedFor(updatedPublishedFor.filter((item) => item !== "all")); + } else { + setPublishedFor(updatedPublishedFor); + } + } + }; + + const save = async (data: ImageSchema) => { + loading(); + const finalTags = tags.join(", "); + const finalTitle = isSwitchOn ? title : data.title; + const finalDescription = articleBody || data.description; + + if (!finalDescription.trim()) { + MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error"); + return; + } + + let requestData: { + title: string; + description: string; + htmlDescription: string; + fileTypeId: string; + categoryId: any; + subCategoryId: any; + uploadedBy: string; + statusId: string; + publishedFor: string; + creatorName: string; + tags: string; + isYoutube: boolean; + isInternationalMedia: boolean; + attachFromScheduleId?: number; // ✅ Tambahkan properti ini + } = { + ...data, + title: finalTitle, + description: finalDescription, + htmlDescription: finalDescription, + fileTypeId, + categoryId: selectedCategory, + subCategoryId: selectedCategory, + uploadedBy: "2b7c8d83-d298-4b19-9f74-b07924506b58", + statusId: "1", + publishedFor: publishedFor.join(","), + creatorName: data.creatorName, + tags: finalTags, + isYoutube: false, + isInternationalMedia: false, + }; + + let id = Cookies.get("idCreate"); + + if (scheduleId !== undefined) { + requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini + } + + if (id == undefined) { + const response = await createMedia(requestData); + console.log("Form Data Submitted:", requestData); + + Cookies.set("idCreate", response?.data?.data, { expires: 1 }); + id = response?.data?.data; + + // Upload Thumbnail + const formMedia = new FormData(); + const thumbnail = files[0]; + formMedia.append("file", thumbnail); + const responseThumbnail = await uploadThumbnail(id, formMedia); + if (responseThumbnail?.error == true) { + error(responseThumbnail?.message); + return false; + } + } + + // Upload File + const progressInfoArr = files.map((item) => ({ + percentage: 0, + fileName: item.name, + })); + progressInfo = progressInfoArr; + setIsStartUpload(true); + setProgressList(progressInfoArr); + + close(); + files.map(async (item: any, index: number) => { + await uploadResumableFile( + index, + String(id), + item, + fileTypeId == "2" || fileTypeId == "4" ? item.duration : "0" + ); + }); + + Cookies.remove("idCreate"); + }; + + 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 resCsrf = await getCsrfToken(); + const csrfToken = resCsrf?.data?.token; + console.log("CSRF TOKEN : ", csrfToken); + const headers = { + "X-XSRF-TOKEN": csrfToken, + }; + + const upload = new Upload(file, { + endpoint: `${process.env.NEXT_PUBLIC_API}/media/file/upload`, + headers: headers, + retryDelays: [0, 3000, 6000, 12_000, 24_000], + chunkSize: 20_000, + metadata: { + mediaid: id, + filename: file.name, + filetype: file.type, + duration, + isWatermark: "true", // hardcode + }, + onBeforeRequest: function (req) { + var xhr = req.getUnderlyingObject(); + xhr.withCredentials = true; + }, + 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/image/"); + } + } + + 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([]); + }; + + useEffect(() => { + // Jika input title kosong, isi dengan hasil generate title + if (!getValues("title") && title) { + setValue("title", title); + } + }, [title, getValues, setValue]); + + return ( +
+
+ +
+
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.title?.message && ( +

{errors.title.message}

+ )} +
+
+
+ + +
+ +
+ + +
+
+ +
+ + + isLoadingData ? ( +
+

Loading Proses Data...

+
+ ) : ( + + ) + } + /> + {errors.description?.message && ( +

+ {errors.description.message} +

+ )} +
+
+ + {/* */} + +
+ +
+ +

+ {/* Drop files here or click to upload. */} + {t("drag-file")} +

+
+ {t("upload-file-max")} +
+
+
+ {files.length ? ( + +
{fileList}
+
+
+ +
+ +
+
+ +
+
+ ) : null} +
+
+
+ + {/* Submit Button */} +
+
+
+ +
+
+ + ( + + )} + /> + {errors.creatorName?.message && ( +

+ {errors.creatorName.message} +

+ )} +
+
+
+ + +
+ {tags.map((tag, index) => ( + + {tag}{" "} + + + ))} +
+
+
+
+ + {options.map((option) => ( +
+ opt.id !== "all") + .length + : publishedFor.includes(option.id) + } + onCheckedChange={() => handleCheckboxChange(option.id)} + /> + +
+ ))} +
+
+
+
+
+ +
+
+ + + +
+
+
+
+
+ ); +} diff --git a/components/form/task/task-edit-form.tsx b/components/form/task/task-edit-form.tsx index 812a981d..a2582ded 100644 --- a/components/form/task/task-edit-form.tsx +++ b/components/form/task/task-edit-form.tsx @@ -692,7 +692,7 @@ export default function FormTaskEdit() {
- +
- +