Merge pull request #139 from bipproduction/amalia/22-agustus-24

Amalia/22 agustus 24
This commit is contained in:
Amalia
2024-08-22 15:30:24 +08:00
committed by GitHub
8 changed files with 380 additions and 143 deletions

View File

@@ -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 });
}
};

View File

@@ -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);

View File

@@ -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);
};

View File

@@ -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[]
}

View File

@@ -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: <FcFolder size={40} />
},
{
id: 2,
name: 'Administrasi',
date: '18/06/2024 14.00 PM',
icon: <FcFolder size={40} />
},
{
id: 3,
name: 'Administrasi',
date: '18/06/2024 14.00 PM',
icon: <FcFolder size={40} />
},
]
export default function DrawerCopyDocuments() {
const [opened, setOpened] = useState(false);
function onCreate(val: boolean) {
if (val) {
toast.success("Sukses! Membuat Folder");
}
setOpened(false)
}
return (
<Box>
<Box h={60} pos={"fixed"} bottom={0} w={{base: "92%", md: "94%"}} style={{
zIndex: 999
}}>
<Grid justify='center'>
<Grid.Col span={6}>
<Button variant="subtle" fullWidth color={WARNA.biruTua} radius={"xl"} onClick={() => setOpened(true)}>BUAT FOLDER BARU</Button>
</Grid.Col>
<Grid.Col span={6}>
<Button variant="filled" fullWidth color={WARNA.biruTua} radius={"xl"}>SALIN</Button>
</Grid.Col>
</Grid>
</Box>
<Box p={10} pb={60}>
{dataDocuments.map((v, i) => {
return (
<Box key={i}>
<Box mt={10} mb={10}>
<Grid align='center'>
<Grid.Col span={12}>
<Group gap={20}>
<Box>
{v.icon}
</Box>
<Flex direction={'column'}>
<Text>{v.name}</Text>
<Text fz={10}>{v.date}</Text>
</Flex>
</Group>
</Grid.Col>
</Grid>
</Box>
<Divider size="xs" />
</Box>
)
})}
</Box>
<Modal styles={{
body: {
borderRadius: 20
},
content: {
borderRadius: 20,
border: `2px solid ${"#828AFC"}`
}
}} opened={opened} onClose={() => setOpened(false)} centered withCloseButton={false}>
<Box p={20}>
<Text ta={"center"} fw={"bold"}>Buat Folder</Text>
<Box mt={20} mb={20}>
<TextInput
styles={{
input: {
color: WARNA.biruTua,
borderRadius: '#828AFC',
borderColor: '#828AFC',
},
}}
size="md"
radius={10}
placeholder="Buat Folder Baru"
/>
</Box>
<Grid mt={40}>
<Grid.Col span={6}>
<Button variant="subtle" fullWidth color='#969494' onClick={() => setOpened(false)}>Batalkan</Button>
</Grid.Col>
<Grid.Col span={6}>
<Button variant="subtle" fullWidth color={WARNA.biruTua} onClick={(val) => onCreate(true)}>Membuat</Button>
</Grid.Col>
</Grid>
</Box>
</Modal>
</Box>
);
}

View File

@@ -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<IDataDocument[]>([])
const [dataJalur, setDataJalur] = useState<IJalurItem[]>([])
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() {
<Button variant="subtle" fullWidth color={WARNA.biruTua} radius={"xl"} onClick={() => setOpened(true)}>BUAT FOLDER BARU</Button>
</Grid.Col>
<Grid.Col span={6}>
<Button variant="filled" fullWidth color={WARNA.biruTua} radius={"xl"}>PINDAH</Button>
<Button variant="filled" fullWidth color={WARNA.biruTua} radius={"xl"} onClick={() => onChoosePath(path)}>
{
(category == "move") ?
"PINDAH" : "SALIN"
}
</Button>
</Grid.Col>
</Grid>
</Box>
<Box p={10} pb={60}>
<Box>
<Breadcrumbs separator={<GoChevronRight />} separatorMargin="md" mt="xs">
{
dataJalur.map((v, i) => {
return (
<Text onClick={() => setPath(v.id)} key={i} style={{ cursor: 'pointer' }}>
{v.name}
</Text>
)
})
}
</Breadcrumbs>
</Box>
{dataDocument.map((v, i) => {
const found = data.some((i: any) => i.id == v.id)
return (
<Box key={i}>
<Box mt={10} mb={10} onClick={() => setPath(v.id)}>
<Box mt={10} mb={10} onClick={() => {
if (!found) {
setPath(v.id)
}
}}>
<Grid align='center'>
<Grid.Col span={12}>
<Group gap={20}>
<Box>
{
(v.category == "FOLDER") ?
<FcFolder size={60} /> :
(v.extension == "pdf" || v.extension == "csv") ?
<FcDocument size={60} /> :
<FcImageFile size={60} />
(found) ?
<MdFolder size={60} color='grey' /> :
<FcFolder size={60} />
}
</Box>
<Flex direction={'column'}>
<Text>{(v.category == "FOLDER") ? v.name : v.name + '.' + v.extension}</Text>
{
(found) && <Text c={'dimmed'} fz={13} fs={'italic'}>Tidak bisa memilih folder ini</Text>
}
</Flex>
</Group>
</Grid.Col>

View File

@@ -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 (
<Box>
<Stack p={10} >
@@ -35,13 +79,11 @@ export default function DrawerMore() {
<LayoutDrawer opened={isCut} onClose={() => setIsCut(false)} title={'Pilih Lokasi Pemindahan'} size="lg">
<DrawerCutDocuments />
<DrawerCutDocuments data={data} onChoosePath={(val) => { onMoveItem(val) }} category="move" />
</LayoutDrawer>
<LayoutDrawer opened={isCopy} onClose={() => setIsCopy(false)} title={'Pilih Lokasi Salin'} size="lg">
<DrawerCopyDocuments />
<DrawerCutDocuments data={data} onChoosePath={(val) => { onCopyItem(val) }} category="copy" />
</LayoutDrawer>
</Box>
);

View File

@@ -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<IDataDocument[]>([])
const [dataJalur, setDataJalur] = useState<IJalurItem[]>([])
const refresh = useHookstate(globalRefreshDocument)
const [selectedFiles, setSelectedFiles] = useState<any>([])
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() {
<Box>
<Box p={20} pb={60}>
<Box>
<Breadcrumbs separator={<GoChevronRight />} separatorMargin="md" mt="xs">
{
dataJalur.map((v, i) => {
return (
<Text onClick={() => router.push('?path=' + v.id)} key={i} style={{ cursor: 'pointer' }}>
{v.name}
</Text>
)
})
}
</Breadcrumbs>
</Box>
{dataDocument.map((v, i) => {
const isSelected = selectedFiles.some((i: any) => i?.id == v.id);
return (
@@ -266,7 +286,7 @@ export default function NavbarDocumentDivision() {
<Grid align='center' >
<Grid.Col span={10}
onClick={() => {
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() {
</Box>
</Box>
</LayoutDrawer>
<LayoutDrawer opened={more} title={''} onClose={() => setMore(false)}>
<DrawerMore />
<DrawerMore data={selectedFiles} />
</LayoutDrawer>
</Box>
);