"use client"; import { FormEvent, Fragment, useEffect, useRef, useState } from "react"; import { Controller, useForm } from "react-hook-form"; import * as z from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; import { Input, Textarea } from "@heroui/input"; import dynamic from "next/dynamic"; import JoditEditor from "jodit-react"; import { useDropzone } from "react-dropzone"; import { Button } from "@heroui/button"; import { CloudUploadIcon, TimesIcon } from "@/components/icons"; import Image from "next/image"; import { Switch } from "@heroui/switch"; import { createArticle, getArticleByCategory, uploadArticleFile, uploadArticleThumbnail, } from "@/services/article"; import ReactSelect from "react-select"; import makeAnimated from "react-select/animated"; import { Checkbox, Chip } from "@heroui/react"; import { getUnixTimestamp, htmlToString } from "@/utils/global"; import { close, error, loading } from "@/config/swal"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { CsvIcon, ExcelIcon, PdfIcon, PptIcon, WordIcon, } from "@/components/icons/globals"; import { createMagazine, uploadMagazineFile, uploadMagazineThumbnail, } from "@/services/magazine"; const CustomEditor = dynamic( () => { return import("@/components/editor/custom-editor"); }, { ssr: false } ); interface FileWithPreview extends File { preview: string; } interface CategoryType { id: number; label: string; value: number; } const categorySchema = z.object({ id: z.number(), label: z.string(), value: z.number(), }); const createArticleSchema = z.object({ title: z.string().min(2, { message: "Judul harus diisi", }), slug: z.string().min(2, { message: "Slug harus diisi", }), description: z.string().min(2, { message: "Deskripsi harus diisi", }), rows: z.array( z.object({ title: z.string().min(1, { message: "Main Keyword must be at least 2 characters.", }), description: z.string().min(1, { message: "Title must be at least 2 characters.", }), }) ), category: z.array(categorySchema).nonempty({ message: "Kategori harus memiliki setidaknya satu item", }), }); export default function NewCreateMagazineForm() { const animatedComponents = makeAnimated(); const MySwal = withReactContent(Swal); const router = useRouter(); const editor = useRef(null); const [files, setFiles] = useState([]); const [thumbnailImg, setThumbnailImg] = useState([]); const [listCategory, setListCategory] = useState([]); useEffect(() => { fetchCategory(); }, []); const fetchCategory = async () => { const res = await getArticleByCategory(getUnixTimestamp()); if (res?.data?.data) { setupCategory(res?.data?.data); } }; const setupCategory = (data: any) => { const temp = []; for (const element of data) { temp.push({ id: element.id, label: element.title, value: element.id, }); } setListCategory(temp); }; const { getRootProps, getInputProps } = useDropzone({ onDrop: (acceptedFiles) => { setFiles((prevFiles) => [ ...prevFiles, ...acceptedFiles.map((file) => Object.assign(file)), ]); }, multiple: true, accept: { "application/pdf": [".pdf"], "application/vnd.openxmlformats-officedocument.presentationml.presentation": [".pptx"], "application/vnd.ms-powerpoint": [".ppt"], "application/vnd.openxmlformats-officedocument.wordprocessingml.document": [".docx"], "application/msword": [".doc"], "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [ ".xlsx", ], }, }); const formOptions = { resolver: zodResolver(createArticleSchema), defaultValues: { title: "", description: "", category: [], tags: [] }, }; type UserSettingSchema = z.infer; const { register, control, handleSubmit, formState: { errors }, setValue, getValues, watch, setError, clearErrors, } = useForm(formOptions); const onSubmit = async (values: z.infer) => { MySwal.fire({ title: "Simpan Data", text: "", icon: "warning", showCancelButton: true, cancelButtonColor: "#d33", confirmButtonColor: "#3085d6", confirmButtonText: "Simpan", }).then((result) => { if (result.isConfirmed) { save(values); } }); }; const save = async (values: z.infer) => { loading(); const formData = { title: values.title, typeId: 1, slug: values.slug, statusId: 1, categoryIds: values.category.map((a) => a.id).join(","), // description: htmlToString(removeImgTags(values.description)), description: values.description, // rows: values.rows, }; console.log("formd", formData); const response = await createMagazine(formData); if (response?.error) { error(response.message); return false; } const magazineId = response?.data?.data?.id; if (files?.length > 0) { const formFiles = new FormData(); for (let i = 0; i < files.length; i++) { formFiles.append("files", files[i]); formFiles.append("title", values.rows[i].title); formFiles.append("file", values.rows[i].description); const resFile = await uploadMagazineFile(magazineId, formFiles); } } if (thumbnailImg?.length > 0) { const formFiles = new FormData(); formFiles.append("files", thumbnailImg[0]); const resFile = await uploadMagazineThumbnail(magazineId, formFiles); } close(); successSubmit("/admin/magazine"); }; function successSubmit(redirect: string) { MySwal.fire({ title: "Sukses", icon: "success", confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then((result) => { if (result.isConfirmed) { router.push(redirect); } }); } const watchTitle = watch("title"); const generateSlug = (title: string) => { return title .toLowerCase() .trim() .replace(/[^\w\s-]/g, "") .replace(/\s+/g, "-"); }; useEffect(() => { setValue("slug", generateSlug(watchTitle)); }, [watchTitle]); const renderPreview = (file: File) => { if (file.type === "application/pdf") { return ; } else if (file.type === "text/csv") { return ; } else if ( file.type === "application/vnd.openxmlformats-officedocument.wordprocessingml.document" || file.type === "application/msword" ) { return ; } else if ( file.type === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" || file.type === "application/vnd.ms-excel" ) { return ; } else if ( file.type === "application/vnd.openxmlformats-officedocument.presentationml.presentation" || file.type === "application/vnd.ms-powerpoint" ) { return ; } else { return "unknown"; } }; const handleRemoveFile = (file: FileWithPreview) => { const uploadedFiles = files; const filtered = uploadedFiles.filter((i) => i.name !== file.name); setFiles([...filtered]); }; const fileList = files.map((file, index) => (
{renderPreview(file)}

Nama 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"}

Judul

setValue(`rows.${index}.title`, e)} labelPlacement="outside" className="w-full " classNames={{ inputWrapper: [ "border-1 rounded-lg", "dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400", ], }} variant="bordered" />

Deskripsi