From e8a17be67785f0f035ce944200de20f6776fdc1d Mon Sep 17 00:00:00 2001 From: amel Date: Mon, 2 Sep 2024 17:20:21 +0800 Subject: [PATCH] upd: dokumen divisi Deskripsi: - uplaod file No Issues --- src/app/api/document/route.ts | 2 +- src/app/api/document/upload/route.ts | 100 ++++++++++++++++++ src/module/document/lib/api_document.ts | 10 +- .../ui/drawer_menu_document_division.tsx | 75 ++++++++++--- 4 files changed, 170 insertions(+), 17 deletions(-) create mode 100644 src/app/api/document/upload/route.ts diff --git a/src/app/api/document/route.ts b/src/app/api/document/route.ts index 440b187..7ddbafd 100644 --- a/src/app/api/document/route.ts +++ b/src/app/api/document/route.ts @@ -181,7 +181,7 @@ export async function GET(request: Request) { allData.push(...formatDataShare) } - const formatData = _.orderBy(allData, ['category', 'name']) + const formatData = _.orderBy(allData, ['category', 'name'], ['desc', 'asc']); let pathNow = path let jalur = [] diff --git a/src/app/api/document/upload/route.ts b/src/app/api/document/upload/route.ts new file mode 100644 index 0000000..787e458 --- /dev/null +++ b/src/app/api/document/upload/route.ts @@ -0,0 +1,100 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import _ from "lodash"; +import { NextResponse } from "next/server"; +import fs from "fs"; +import path from "path"; + + +// UPLOAD FILE +export async function POST(request: Request) { + try { + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + + const body = await request.formData() + const dataBody = body.get("data") + const file = body.get("file") as File + const fileName = file.name + + + const { idPath, idDivision } = JSON.parse(dataBody as string) + + const cekDivision = await prisma.division.count({ + where: { + id: String(idDivision), + isActive: true + } + }) + + if (cekDivision == 0) { + return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan" }, { status: 404 }); + } + + if (idPath != "home") { + const cekPath = await prisma.divisionDocumentFolderFile.count({ + where: { + isActive: true, + id: idPath + } + }) + + if (cekPath == 0) { + return NextResponse.json({ success: false, message: "Gagal mendapatkan path, data tidak ditemukan" }, { status: 404 }); + } + } + + const nameFile = await prisma.divisionDocumentFolderFile.findMany({ + where: { + idDivision, + path: idPath, + category: "FILE", + isActive: true + } + }) + + const dataOmit = nameFile.map((v: any) => ({ + ..._.omit(v, [""]), + file: v.name + '.' + v.extension, + })) + + const cek = dataOmit.some((i: any) => i.file == fileName) + + if (cek) { + return NextResponse.json({ success: false, message: "Terdapat file dengan nama yang sama" }, { status: 400 }); + } + + + const fExt = file.name.split(".").pop() + const fName = file.name.replace("." + fExt, "") + + const dataInsert = await prisma.divisionDocumentFolderFile.create({ + data: { + name: fName, + path: idPath, + idDivision, + category: "FILE", + extension: String(fExt), + createdBy: user.id, + }, + select: { + id: true + } + }); + + const root = path.join(process.cwd(), "./public/file/dokumen/"); + const nameFix = dataInsert.id + '.' + fExt + const filePath = path.join(root, nameFix) + // Konversi ArrayBuffer ke Buffer + const buffer = Buffer.from(await file.arrayBuffer()); + // Tulis file ke sistem + fs.writeFileSync(filePath, buffer); + + return NextResponse.json({ success: true, message: "Berhasil upload file" }, { status: 200 }); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal upload file, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +}; \ No newline at end of file diff --git a/src/module/document/lib/api_document.ts b/src/module/document/lib/api_document.ts index 6d9cfad..d7c218f 100644 --- a/src/module/document/lib/api_document.ts +++ b/src/module/document/lib/api_document.ts @@ -77,4 +77,12 @@ export const funShareDocument = async (data: IShareDocument) => { body: JSON.stringify(data), }); return await response.json().catch(() => null); -}; \ No newline at end of file +}; + +export const funUploadFileDocument = async (data: FormData) => { + const response = await fetch(`/api/document/upload`, { + method: "POST", + body: data, + }); + return await response.json().catch(() => null); +} \ No newline at end of file diff --git a/src/module/document/ui/drawer_menu_document_division.tsx b/src/module/document/ui/drawer_menu_document_division.tsx index 01165c0..18b0a31 100644 --- a/src/module/document/ui/drawer_menu_document_division.tsx +++ b/src/module/document/ui/drawer_menu_document_division.tsx @@ -2,14 +2,16 @@ import { LayoutDrawer, WARNA } from '@/module/_global'; import { ActionIcon, Box, Button, Divider, Flex, Grid, Modal, SimpleGrid, Stack, Text, TextInput } from '@mantine/core'; import { useParams, useRouter, useSearchParams } from 'next/navigation'; -import React, { useState } from 'react'; +import React, { useRef, useState } from 'react'; import toast from 'react-hot-toast'; import { FaFolderClosed, FaRegImage } from 'react-icons/fa6'; import { HiDocumentText } from 'react-icons/hi2'; import { IoAddCircle, IoDocumentText } from 'react-icons/io5'; -import { funCreateFolder } from '../lib/api_document'; +import { funCreateFolder, funUploadFileDocument } from '../lib/api_document'; import { useHookstate } from '@hookstate/core'; import { globalRefreshDocument } from '../lib/val_document'; +import { Dropzone } from '@mantine/dropzone'; +import _ from 'lodash'; export default function DrawerMenuDocumentDivision() { const [openDrawerDocument, setOpenDrawerDocument] = useState(false) @@ -19,6 +21,8 @@ export default function DrawerMenuDocumentDivision() { const searchParams = useSearchParams() const path = searchParams.get('path') const refresh = useHookstate(globalRefreshDocument) + const openRef = useRef<() => void>(null) + const [fileForm, setFileForm] = useState() const [bodyFolder, setBodyFolder] = useState({ name: '', @@ -42,6 +46,29 @@ export default function DrawerMenuDocumentDivision() { setOpenDrawerDocument(false) } + async function onUploadFile(data: any) { + try { + const fd = new FormData() + fd.append(`file`, data) + fd.append("data", JSON.stringify({ + idPath: (path == undefined || path == '' || path == null) ? 'home' : path, + idDivision: param.id + })) + + const res = await funUploadFileDocument(fd) + if (!res.success) { + toast.error(res.message) + } + } catch (error) { + console.error(error); + toast.error("Gagal upload file, coba lagi nanti"); + } + + refresh.set(true) + setOpenModal(false) + setOpenDrawerDocument(false) + } + return ( @@ -59,11 +86,13 @@ export default function DrawerMenuDocumentDivision() { - setOpenDrawerDocument(false)} title={''} size='lg' > + + setOpenDrawerDocument(false)} title={''}> setOpenDrawerDocument(true)} > + setOpenModal(true)} justify={'center'} align={'center'} direction={'column'} mb={20} > @@ -74,17 +103,33 @@ export default function DrawerMenuDocumentDivision() { Membuat Folder - - - - - - - - Upload Dokumen - - - + { + if (!files || _.isEmpty(files)) + return toast.error('Tidak ada file yang dipilih') + onUploadFile(files[0]) + }} + activateOnClick={false} + maxSize={3 * 1024 ** 2} + accept={['text/csv', 'image/png', 'image/jpeg', 'image/heic', 'application/pdf']} + onReject={(files) => { + return toast.error('File yang diizinkan: .csv, .png, .jpg, .heic, .pdf dengan ukuran maksimal 3 MB') + }} + > + openRef.current?.()}> + + + + + + + Upload File + + + + + {/* @@ -93,7 +138,7 @@ export default function DrawerMenuDocumentDivision() { Upload Foto - + */}