diff --git a/src/app/api/document/more/route.ts b/src/app/api/document/more/route.ts index f4a77c7..60cead8 100644 --- a/src/app/api/document/more/route.ts +++ b/src/app/api/document/more/route.ts @@ -1,6 +1,8 @@ +import { prisma } from "@/module/_global"; import { funGetUserByCookies } from "@/module/auth"; import { NextResponse } from "next/server"; + // MOVE ITEM export async function POST(request: Request) { try { @@ -9,9 +11,177 @@ export async function POST(request: Request) { return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); } + const { path, dataItem } = (await request.json()); + + + if (path != "home") { + const cekPath = await prisma.divisionDocumentFolderFile.count({ + where: { + isActive: true, + id: path + } + }) + + if (cekPath == 0) { + return NextResponse.json({ success: false, message: "Gagal mendapatkan path, data tidak ditemukan" }, { status: 404 }); + } + } + + for (let i = 0; i < dataItem.length; i++) { + + let status = false + let numb = 1 + let name = dataItem[i].name + do { + const cekName = await prisma.divisionDocumentFolderFile.count({ + where: { + path: path, + isActive: true, + extension: dataItem[i].extension, + name + } + }) + + if (cekName > 0) { + name = dataItem[i].name + " (" + numb + ")" + numb++ + status = false + } else { + status = true + } + } while (status == false); + + + const id = dataItem[i].id; + const update = await prisma.divisionDocumentFolderFile.update({ + where: { + id + }, + data: { + path, + name + } + }) + } + + return NextResponse.json({ success: true, message: "Berhasil memindahkan item" }, { status: 200 }); } catch (error) { console.log(error); return NextResponse.json({ success: false, message: "Gagal memindahkan item, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); } +}; + + +// COPY ITEM +export async function PUT(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 { idDivision, path, dataItem } = (await request.json()); + + + if (path != "home") { + const cekPath = await prisma.divisionDocumentFolderFile.count({ + where: { + isActive: true, + id: path + } + }) + + if (cekPath == 0) { + return NextResponse.json({ success: false, message: "Gagal mendapatkan path, data tidak ditemukan" }, { status: 404 }); + } + } + + for (let i = 0; i < dataItem.length; i++) { + let name = dataItem[i].name; + const category = dataItem[i].category; + const extension = dataItem[i].extension; + + let status = false + let numb = 1 + do { + const cekName = await prisma.divisionDocumentFolderFile.count({ + where: { + path: path, + isActive: true, + extension, + name + } + }) + + if (cekName > 0) { + name = dataItem[i].name + " (" + numb + ")" + numb++ + status = false + } else { + status = true + } + } while (status == false); + + + const create = await prisma.divisionDocumentFolderFile.create({ + data: { + name, + path, + idDivision, + category, + extension, + createdBy: user.id + }, + select: { + id: true + } + }) + + // let newPath = create.id + // let idPath = dataItem[i].id; + // let statusCek = false + // do { + // const cekFolder = await prisma.divisionDocumentFolderFile.findMany({ + // where: { + // isActive: true, + // path: idPath + // } + // }) + + // if (cekFolder.length == 0) { + // statusCek = true + // } else { + // for (let index = 0; index < cekFolder.length; index++) { + // const addChildren = await prisma.divisionDocumentFolderFile.create({ + // data: { + // name: cekFolder[index].name, + // path: newPath, + // idDivision, + // category: cekFolder[index].category, + // extension: cekFolder[index].extension, + // createdBy: user.id + // }, + // select: { + // id: true + // } + // }) + + // newPath = create.id + // } + + + // } + + + // } while (statusCek == false); + + } + + + return NextResponse.json({ success: true, message: "Berhasil salin item" }, { status: 200 }); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal salin item, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } }; \ No newline at end of file diff --git a/src/app/api/document/route.ts b/src/app/api/document/route.ts index 331595d..6c21827 100644 --- a/src/app/api/document/route.ts +++ b/src/app/api/document/route.ts @@ -17,6 +17,7 @@ export async function GET(request: Request) { const { searchParams } = new URL(request.url); const idDivision = searchParams.get("division"); const path = searchParams.get("path"); + const category = searchParams.get("category"); const cekDivision = await prisma.division.count({ where: { @@ -43,14 +44,24 @@ export async function GET(request: Request) { } + let kondisi: any = { + isActive: true, + idDivision: String(idDivision), + path: (path == "undefined" || path == "null" || path == "" || path == null) ? "home" : path + } + + if (category == "folder") { + kondisi = { + isActive: true, + idDivision: String(idDivision), + path: (path == "undefined" || path == "null" || path == "" || path == null) ? "home" : path, + category: "FOLDER" + } + } const data = await prisma.divisionDocumentFolderFile.findMany({ - where: { - isActive: true, - idDivision: String(idDivision), - path: (path == "undefined" || path == "null" || path == "" || path == null) ? "home" : path - }, + where: kondisi, select: { id: true, category: true, @@ -78,7 +89,35 @@ export async function GET(request: Request) { })) - return NextResponse.json({ success: true, message: "Berhasil mendapatkan item", data: allData, }, { status: 200 }); + let pathNow = path + let jalur = [] + + if (path != "home" && path != "null" && path != "undefined" && path != "") { + do { + const dataPath = await prisma.divisionDocumentFolderFile.findUnique({ + where: { + id: String(pathNow) + } + }) + + if (dataPath) { + const fix = { + id: String(pathNow), + name: dataPath.name, + } + jalur.push(fix) + pathNow = dataPath.path + } else { + pathNow = "home" + } + } while (pathNow != "home"); + + } + + jalur.push({ id: 'home', name: 'home' }) + jalur = [...jalur].reverse() + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan item", data: allData, jalur }, { status: 200 }); } catch (error) { console.log(error); diff --git a/src/module/document/lib/api_document.ts b/src/module/document/lib/api_document.ts index afc3e86..93f419f 100644 --- a/src/module/document/lib/api_document.ts +++ b/src/module/document/lib/api_document.ts @@ -1,4 +1,4 @@ -import { IFormEditItem, IFormFolder } from "./type_document"; +import { IFormEditItem, IFormFolder, IFormMoreCopyItem, IFormMoreItem } from "./type_document"; export const funGetAllDocument = async (path?: string) => { const response = await fetch(`/api/document${(path) ? path : ''}`, { next: { tags: ['document'] } }); @@ -43,4 +43,26 @@ export const funDeleteDocument = async (data: []) => { body: JSON.stringify(data), }); return await response.json().catch(() => null); +}; + +export const funMoveDocument = async (data: IFormMoreItem) => { + const response = await fetch("/api/document/more", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +}; + +export const funCopyDocument = async (data: IFormMoreCopyItem) => { + const response = await fetch("/api/document/more", { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); }; \ No newline at end of file diff --git a/src/module/document/lib/type_document.ts b/src/module/document/lib/type_document.ts index 9f2dbb0..635bb18 100644 --- a/src/module/document/lib/type_document.ts +++ b/src/module/document/lib/type_document.ts @@ -16,6 +16,11 @@ export interface IFormFolder { idDivision: string } +export interface IJalurItem { + id: string + name: string +} + export interface IFormEditItem { id: string @@ -23,4 +28,20 @@ export interface IFormEditItem { path: string idDivision: string extension: string +} + +export interface IFormDetailMoreItem { + id: string + name: string +} + +export interface IFormMoreItem { + path: string, + dataItem: IFormDetailMoreItem[] +} + +export interface IFormMoreCopyItem { + idDivision: string, + path: string, + dataItem: IDataDocument[] } \ No newline at end of file diff --git a/src/module/document/ui/drawer_copy_documents.tsx b/src/module/document/ui/drawer_copy_documents.tsx deleted file mode 100644 index 0eea0a8..0000000 --- a/src/module/document/ui/drawer_copy_documents.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { WARNA } from '@/module/_global'; -import { Box, Button, Divider, Flex, Grid, Group, Modal, Text, TextInput } from '@mantine/core'; -import React, { useState } from 'react'; -import toast from 'react-hot-toast'; -import { FcFolder } from 'react-icons/fc'; -const dataDocuments = [ - { - id: 1, - name: 'Administrasi', - date: '18/06/2024 14.00 PM', - icon: - }, - { - id: 2, - name: 'Administrasi', - date: '18/06/2024 14.00 PM', - icon: - }, - { - id: 3, - name: 'Administrasi', - date: '18/06/2024 14.00 PM', - icon: - }, -] - -export default function DrawerCopyDocuments() { - const [opened, setOpened] = useState(false); - function onCreate(val: boolean) { - if (val) { - toast.success("Sukses! Membuat Folder"); - } - setOpened(false) - } - return ( - - - - - - - - - - - - - {dataDocuments.map((v, i) => { - return ( - - - - - - - {v.icon} - - - {v.name} - {v.date} - - - - - - - - ) - })} - - setOpened(false)} centered withCloseButton={false}> - - Buat Folder - - - - - - - - - - - - - - - ); -} diff --git a/src/module/document/ui/drawer_cut_documents.tsx b/src/module/document/ui/drawer_cut_documents.tsx index 7677160..35eb093 100644 --- a/src/module/document/ui/drawer_cut_documents.tsx +++ b/src/module/document/ui/drawer_cut_documents.tsx @@ -1,18 +1,23 @@ import { WARNA } from '@/module/_global'; -import { Box, Button, Divider, Flex, Grid, Group, Modal, Text, TextInput } from '@mantine/core'; +import { Box, Breadcrumbs, Button, Divider, Flex, Grid, Group, Modal, Text, TextInput } from '@mantine/core'; import React, { useState } from 'react'; import toast from 'react-hot-toast'; -import { FcDocument, FcFolder, FcImageFile } from 'react-icons/fc'; -import { funCreateFolder, funGetAllDocument } from '../lib/api_document'; +import { FcFolder } from 'react-icons/fc'; +import { funCreateFolder, funGetAllDocument, funMoveDocument } from '../lib/api_document'; import { useParams } from 'next/navigation'; -import { IDataDocument } from '../lib/type_document'; +import { IDataDocument, IFormDetailMoreItem, IJalurItem } from '../lib/type_document'; import { useShallowEffect } from '@mantine/hooks'; +import { MdFolder } from 'react-icons/md'; +import router from 'next/router'; +import { GoChevronRight } from 'react-icons/go'; -export default function DrawerCutDocuments() { + +export default function DrawerCutDocuments({ category, onChoosePath, data }: { category: string, data: IFormDetailMoreItem[], onChoosePath: (val: string) => void }) { const [opened, setOpened] = useState(false); const param = useParams<{ id: string }>() const [path, setPath] = useState('home') const [dataDocument, setDataDocument] = useState([]) + const [dataJalur, setDataJalur] = useState([]) const [valName, setValName] = useState('') @@ -36,12 +41,12 @@ export default function DrawerCutDocuments() { setOpened(false) } - async function getOneData() { try { - const respon = await funGetAllDocument("?division=" + param.id + "&path=" + path); + const respon = await funGetAllDocument("?division=" + param.id + "&path=" + path + "&category=folder"); if (respon.success) { setDataDocument(respon.data); + setDataJalur(respon.jalur); } else { toast.error(respon.message); } @@ -66,29 +71,54 @@ export default function DrawerCutDocuments() { - + + + } separatorMargin="md" mt="xs"> + { + dataJalur.map((v, i) => { + return ( + setPath(v.id)} key={i} style={{ cursor: 'pointer' }}> + {v.name} + + ) + }) + } + + {dataDocument.map((v, i) => { + const found = data.some((i: any) => i.id == v.id) return ( - setPath(v.id)}> + { + if (!found) { + setPath(v.id) + } + }}> { - (v.category == "FOLDER") ? - : - (v.extension == "pdf" || v.extension == "csv") ? - : - + (found) ? + : + } {(v.category == "FOLDER") ? v.name : v.name + '.' + v.extension} + { + (found) && Tidak bisa memilih folder ini + } diff --git a/src/module/document/ui/drawer_more.tsx b/src/module/document/ui/drawer_more.tsx index 9db2302..e378ac1 100644 --- a/src/module/document/ui/drawer_more.tsx +++ b/src/module/document/ui/drawer_more.tsx @@ -3,11 +3,55 @@ import { Box, Flex, Group, SimpleGrid, Stack, Text } from "@mantine/core"; import React, { useState } from "react"; import { LuFolders, LuFolderSymlink } from "react-icons/lu"; import DrawerCutDocuments from "./drawer_cut_documents"; -import DrawerCopyDocuments from "./drawer_copy_documents"; +import { IDataDocument, IFormDetailMoreItem } from "../lib/type_document"; +import toast from "react-hot-toast"; +import { funCopyDocument, funMoveDocument } from "../lib/api_document"; +import { useHookstate } from "@hookstate/core"; +import { globalRefreshDocument } from "../lib/val_document"; +import { useParams } from "next/navigation"; -export default function DrawerMore() { +export default function DrawerMore({ data }: { data: IDataDocument[] }) { const [isCut, setIsCut] = useState(false) const [isCopy, setIsCopy] = useState(false) + const refresh = useHookstate(globalRefreshDocument) + const param = useParams<{ id: string }>() + + + async function onMoveItem(path: string) { + try { + const res = await funMoveDocument({ path, dataItem: data }) + if (res.success) { + toast.success(res.message) + refresh.set(true) + } else { + toast.error(res.message) + } + } catch (error) { + console.log(error) + toast.error("Gagal memindahkan item, coba lagi nanti") + } + setIsCut(false) + } + + + async function onCopyItem(path: string) { + try { + const res = await funCopyDocument({ idDivision: param.id, path, dataItem: data }) + if (res.success) { + toast.success(res.message) + refresh.set(true) + } else { + toast.error(res.message) + } + } catch (error) { + console.log(error) + toast.error("Gagal memindahkan item, coba lagi nanti") + } + setIsCopy(false) + } + + + return ( @@ -35,13 +79,11 @@ export default function DrawerMore() { setIsCut(false)} title={'Pilih Lokasi Pemindahan'} size="lg"> - + { onMoveItem(val) }} category="move" /> - - setIsCopy(false)} title={'Pilih Lokasi Salin'} size="lg"> - + { onCopyItem(val) }} category="copy" /> ); diff --git a/src/module/document/ui/navbar_document_division.tsx b/src/module/document/ui/navbar_document_division.tsx index 0f0a319..cae6f92 100644 --- a/src/module/document/ui/navbar_document_division.tsx +++ b/src/module/document/ui/navbar_document_division.tsx @@ -1,6 +1,6 @@ 'use client' import { LayoutDrawer, LayoutNavbarNew, WARNA } from '@/module/_global'; -import { ActionIcon, Box, Button, Checkbox, Divider, Flex, Grid, Group, Modal, Select, SimpleGrid, Text, TextInput } from '@mantine/core'; +import { ActionIcon, Anchor, Box, Breadcrumbs, Button, Checkbox, Divider, Flex, Grid, Group, Modal, Select, SimpleGrid, Text, TextInput } from '@mantine/core'; import React, { useState } from 'react'; import { HiMenu } from 'react-icons/hi'; import { FcDocument, FcFolder, FcImageFile } from 'react-icons/fc'; @@ -17,10 +17,11 @@ import DrawerMore from './drawer_more'; import { funGetDivisionById } from '@/module/division_new'; import { useShallowEffect } from '@mantine/hooks'; import { funDeleteDocument, funGetAllDocument, funRenameDocument } from '../lib/api_document'; -import { IDataDocument } from '../lib/type_document'; +import { IDataDocument, IJalurItem } from '../lib/type_document'; import { useHookstate } from '@hookstate/core'; import { globalRefreshDocument } from '../lib/val_document'; import { RiListCheck } from 'react-icons/ri'; +import { GoChevronRight } from 'react-icons/go'; export default function NavbarDocumentDivision() { const router = useRouter() @@ -34,6 +35,7 @@ export default function NavbarDocumentDivision() { const searchParams = useSearchParams() const path = searchParams.get('path') const [dataDocument, setDataDocument] = useState([]) + const [dataJalur, setDataJalur] = useState([]) const refresh = useHookstate(globalRefreshDocument) const [selectedFiles, setSelectedFiles] = useState([]) const [selectAll, setSelectAll] = useState(false) @@ -57,7 +59,8 @@ export default function NavbarDocumentDivision() { id: dataDocument[index].id, name: dataDocument[index].name, path: dataDocument[index].path, - extension: dataDocument[index].extension + extension: dataDocument[index].extension, + category: dataDocument[index].category, } ]) } @@ -81,7 +84,8 @@ export default function NavbarDocumentDivision() { id: dataDocument[index].id, name: dataDocument[index].name, path: dataDocument[index].path, - extension: dataDocument[index].extension + extension: dataDocument[index].extension, + category: dataDocument[index].category, } setSelectedFiles((selectedFiles: any) => [...selectedFiles, newArr]) } @@ -146,6 +150,7 @@ export default function NavbarDocumentDivision() { const respon = await funGetAllDocument("?division=" + param.id + "&path=" + path); if (respon.success) { setDataDocument(respon.data); + setDataJalur(respon.jalur); } else { toast.error(respon.message); } @@ -166,6 +171,8 @@ export default function NavbarDocumentDivision() { function resetRefresh() { refresh.set(false) setOpen(false) + setMore(false) + handleBatal() } useShallowEffect(() => { @@ -258,6 +265,19 @@ export default function NavbarDocumentDivision() { + + } separatorMargin="md" mt="xs"> + { + dataJalur.map((v, i) => { + return ( + router.push('?path=' + v.id)} key={i} style={{ cursor: 'pointer' }}> + {v.name} + + ) + }) + } + + {dataDocument.map((v, i) => { const isSelected = selectedFiles.some((i: any) => i?.id == v.id); return ( @@ -266,7 +286,7 @@ export default function NavbarDocumentDivision() { { - if (v.category == "FOLDER") + if (v.category == "FOLDER" && selectedFiles.length == 0 && !dariSelectAll) router.push('?path=' + v.id) }} > @@ -397,8 +417,11 @@ export default function NavbarDocumentDivision() { + + + setMore(false)}> - + );