From ad6bd2cbfb626fcb82786a257c890cb140423a8c Mon Sep 17 00:00:00 2001 From: amel Date: Thu, 12 Sep 2024 15:39:09 +0800 Subject: [PATCH] upd: task divisi Deskripsi: - upload file - view file No Issues --- prisma/schema.prisma | 1 + src/app/api/task/[id]/route.ts | 6 +- src/app/api/task/file/[id]/route.ts | 57 ++--- src/app/api/task/route.ts | 45 ++-- src/module/task/lib/type_task.ts | 3 +- src/module/task/ui/create_date_end_task.tsx | 46 ++-- src/module/task/ui/create_task.tsx | 249 ++++++++++--------- src/module/task/ui/create_users_project.tsx | 26 +- src/module/task/ui/detail_list_file_task.tsx | 5 +- 9 files changed, 226 insertions(+), 212 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 83e6a62..181d275 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -452,6 +452,7 @@ model ContainerFileDivision { id String @id @default(cuid()) Division Division @relation(fields: [idDivision], references: [id]) idDivision String + idStorage String? name String extension String isActive Boolean @default(true) diff --git a/src/app/api/task/[id]/route.ts b/src/app/api/task/[id]/route.ts index 1b613c4..1ae287f 100644 --- a/src/app/api/task/[id]/route.ts +++ b/src/app/api/task/[id]/route.ts @@ -90,7 +90,8 @@ export async function GET(request: Request, context: { params: { id: string } }) select: { id: true, name: true, - extension: true + extension: true, + idStorage: true } } } @@ -101,6 +102,7 @@ export async function GET(request: Request, context: { params: { id: string } }) nameInStorage: v.ContainerFileDivision.id, name: v.ContainerFileDivision.name, extension: v.ContainerFileDivision.extension, + idStorage: v.ContainerFileDivision.idStorage, })) allData = fix @@ -287,7 +289,7 @@ export async function PUT(request: Request, context: { params: { id: string } }) // create log user const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data tugas divisi', table: 'divisionProject', data: id }) - return NextResponse.json( { success: true, message: "Tugas berhasil diedit", }, { status: 200 } ); + return NextResponse.json({ success: true, message: "Tugas berhasil diedit", }, { status: 200 }); } catch (error) { console.error(error); return NextResponse.json({ success: false, message: "Gagal mengedit tugas, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); diff --git a/src/app/api/task/file/[id]/route.ts b/src/app/api/task/file/[id]/route.ts index 429e74a..7796b3f 100644 --- a/src/app/api/task/file/[id]/route.ts +++ b/src/app/api/task/file/[id]/route.ts @@ -1,4 +1,4 @@ -import { prisma } from "@/module/_global"; +import { DIR, funDeleteFile, funUploadFile, prisma } from "@/module/_global"; import { funGetUserByCookies } from "@/module/auth"; import _ from "lodash"; import { NextResponse } from "next/server"; @@ -42,7 +42,7 @@ export async function DELETE(request: Request, context: { params: { id: string } } }) - fs.unlink(`./public/file/task/${dataFile?.id}.${dataFile?.extension}`, (err) => { }) + await funDeleteFile({ fileId: String(dataFile?.idStorage) }) const deleteRelasi = await prisma.divisionProjectFile.delete({ where: { @@ -57,7 +57,7 @@ export async function DELETE(request: Request, context: { params: { id: string } }); // create log user - const log = await createLogUser({ act: 'DELETE', desc: 'User menghpus file divisi', table: 'divisionProject', data: String(dataRelasi?.idProject) }) + const log = await createLogUser({ act: 'DELETE', desc: 'User menghapus file tugas divisi', table: 'divisionProject', data: String(dataRelasi?.idProject) }) return NextResponse.json({ success: true, message: "File berhasil dihapus", data, }, { status: 200 }); @@ -115,34 +115,29 @@ export async function POST(request: Request, context: { params: { id: string } } const fName = file.name.replace("." + fExt, "") - const insertToContainer = await prisma.containerFileDivision.create({ - data: { - idDivision: String(dataProject?.idDivision), - name: fName, - extension: String(fExt) - }, - select: { - id: true + const upload = await funUploadFile({ file: file, dirId: DIR.task }) + if (upload.success) { + const insertToContainer = await prisma.containerFileDivision.create({ + data: { + idDivision: String(dataProject?.idDivision), + name: fName, + extension: String(fExt), + idStorage: upload.data.id + }, + select: { + id: true + } + }) + + const dataFile = { + idProject: id, + idDivision: dataProject?.idDivision, + idFile: insertToContainer.id, + createdBy: user.id, } - }) - const nameFix = insertToContainer.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); - - - const dataFile = { - idProject: id, - idDivision: dataProject?.idDivision, - idFile: insertToContainer.id, - createdBy: user.id, + fileFix.push(dataFile) } - - - fileFix.push(dataFile) } } @@ -152,12 +147,12 @@ export async function POST(request: Request, context: { params: { id: string } } } // create log user - const log = await createLogUser({ act: 'CREATE', desc: 'User meambahkan file tugas divisi baru', table: 'divisionProject', data: id }) - return NextResponse.json({ success: true, message: "Berhasil membuat tugas divisi" }, { status: 200 }); + const log = await createLogUser({ act: 'CREATE', desc: 'User menambahkan file tugas divisi baru', table: 'divisionProject', data: id }) + return NextResponse.json({ success: true, message: "Berhasil menambahkan file" }, { status: 200 }); } catch (error) { console.error(error); - return NextResponse.json({ success: false, message: "Gagal membuat tugas divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + return NextResponse.json({ success: false, message: "Gagal menambahkan filae, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); } } diff --git a/src/app/api/task/route.ts b/src/app/api/task/route.ts index 76d524a..3093cf6 100644 --- a/src/app/api/task/route.ts +++ b/src/app/api/task/route.ts @@ -1,4 +1,4 @@ -import { prisma } from "@/module/_global"; +import { DIR, funUploadFile, prisma } from "@/module/_global"; import { funGetUserByCookies } from "@/module/auth"; import _, { ceil } from "lodash"; import { NextResponse } from "next/server"; @@ -153,42 +153,35 @@ export async function POST(request: Request) { let fileFix: any[] = [] if (cekFile) { - const root = path.join(process.cwd(), "./public/file/task/"); for (var pair of body.entries()) { if (String(pair[0]).substring(0, 4) == "file") { const file = body.get(pair[0]) as File const fExt = file.name.split(".").pop() const fName = file.name.replace("." + fExt, "") + const upload = await funUploadFile({ file: file, dirId: DIR.task }) + if (upload.success) { + const insertToContainer = await prisma.containerFileDivision.create({ + data: { + idDivision: idDivision, + name: fName, + extension: String(fExt), + idStorage: upload.data.id + }, + select: { + id: true + } + }) - const insertToContainer = await prisma.containerFileDivision.create({ - data: { + const dataFile = { + idProject: data.id, idDivision: idDivision, - name: fName, - extension: String(fExt) - }, - select: { - id: true + idFile: insertToContainer.id, + createdBy: user.id, } - }) - const nameFix = insertToContainer.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); - - - const dataFile = { - idProject: data.id, - idDivision: idDivision, - idFile: insertToContainer.id, - createdBy: user.id, + fileFix.push(dataFile) } - - - fileFix.push(dataFile) } } diff --git a/src/module/task/lib/type_task.ts b/src/module/task/lib/type_task.ts index 8fe2363..bcadba5 100644 --- a/src/module/task/lib/type_task.ts +++ b/src/module/task/lib/type_task.ts @@ -68,5 +68,6 @@ export interface IDataFileTaskDivision { id: string name: string extension: string, - nameInStorage: string + nameInStorage: string, + idStorage: string } \ No newline at end of file diff --git a/src/module/task/ui/create_date_end_task.tsx b/src/module/task/ui/create_date_end_task.tsx index 573b126..f84295c 100644 --- a/src/module/task/ui/create_date_end_task.tsx +++ b/src/module/task/ui/create_date_end_task.tsx @@ -1,6 +1,7 @@ "use client"; import { LayoutNavbarNew, WARNA } from "@/module/_global"; import { + ActionIcon, Avatar, Box, Button, @@ -19,9 +20,10 @@ import { useParams, useRouter } from "next/navigation"; import toast from "react-hot-toast"; import { IFormDateTask } from "../lib/type_task"; import moment from "moment"; +import { HiChevronLeft } from "react-icons/hi2"; -export default function ViewDateEndTask({ onClose }: { onClose: (val: IFormDateTask) => void }) { +export default function ViewDateEndTask({ onClose, onSet }: {onClose: (val: boolean) => void, onSet: (val: IFormDateTask) => void }) { const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); const router = useRouter() const param = useParams<{ id: string }>() @@ -37,7 +39,7 @@ export default function ViewDateEndTask({ onClose }: { onClose: (val: IFormDateT if (title == "") return toast.error("Error! harus memasukkan judul tugas") - onClose( + onSet( { dateStart: value[0], dateEnd: value[1], @@ -49,7 +51,13 @@ export default function ViewDateEndTask({ onClose }: { onClose: (val: IFormDateT return ( - + + { onClose(true) }} bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings"> + + + + } title={"Tanggal Tugas"} menu /> - - - + + + ); } diff --git a/src/module/task/ui/create_task.tsx b/src/module/task/ui/create_task.tsx index e6e8e81..576ff01 100644 --- a/src/module/task/ui/create_task.tsx +++ b/src/module/task/ui/create_task.tsx @@ -76,7 +76,7 @@ export default function CreateTask() { if (response.success) { toast.success(response.message) - // setTitle("") + setTitle("") member.set([]) setFileForm([]) setListFile([]) @@ -92,7 +92,7 @@ export default function CreateTask() { } - if (openTugas) return { + if (openTugas) return { setOpenTugas(false) }} onSet={(val) => { setDataTask([...dataTask, val]) setOpenTugas(false) }} />; @@ -148,7 +148,10 @@ export default function CreateTask() { border: `1px solid ${"#D6D8F6"}`, borderRadius: 10, }} - onClick={() => setOpenDrawer(true)} + onClick={() => + // setOpenDrawer(true) + openRef.current?.() + } > Upload File @@ -168,103 +171,103 @@ export default function CreateTask() { - { - dataTask.length > 0 && - - Tanggal & Tugas - { - dataTask.map((v, i) => { - return ( - { - setIndexDelTask(i) - setOpenDrawerTask(true) - }}> - - - ) - }) - } - - } - - { - listFile.length > 0 && - - File - + { + dataTask.length > 0 && + + Tanggal & Tugas { - listFile.map((v, i) => { + dataTask.map((v, i) => { return ( { - setIndexDelFile(i) - setOpenDrawerFile(true) + setIndexDelTask(i) + setOpenDrawerTask(true) }}> - + ) }) } - - } + } - - { - member.length > 0 && - - - Anggota Terpilih - Total {member.length} Anggota - - - - - {member.get().map((v: any, i: any) => { + { + listFile.length > 0 && + + File + + { + listFile.map((v, i) => { return ( - - - - - - - - {v.name} - - - - - - - Anggota - - - - - + { + setIndexDelFile(i) + setOpenDrawerFile(true) + }}> + + + ) + }) + } + + + } + + + { + member.length > 0 && + + + Anggota Terpilih + Total {member.length} Anggota + + + + + {member.get().map((v: any, i: any) => { + return ( + + + + + + + + {v.name} + + + + + + + Anggota + + + + + + - - ); - })} + ); + })} + - - } + } + { + if (!files || _.isEmpty(files)) + return toast.error('Tidak ada file yang dipilih') + setFileForm([...fileForm, files[0]]) + setListFile([...listFile, { name: files[0].name, extension: files[0].type.split("/")[1] }]) + }} + 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') + }} + > + {/* Drawer pilih file */} - setOpenDrawer(false)} title={"Pilih File"} > - { - if (!files || _.isEmpty(files)) - return toast.error('Tidak ada file yang dipilih') - setFileForm([...fileForm, files[0]]) - setListFile([...listFile, { name: files[0].name, extension: files[0].type.split("/")[1] }]) - }} - 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?.()}> - -
- -
-
- - Pilih file - - diperangkat + + openRef.current?.()}> + +
+ +
-
- {/* router.push("/task/create?page=file-save")}> + + Pilih file + + diperangkat + + + router.push("/task/create?page=file-save")}> sudah ada - */} +
-
+ */} diff --git a/src/module/task/ui/create_users_project.tsx b/src/module/task/ui/create_users_project.tsx index b56e2fb..9428b6b 100644 --- a/src/module/task/ui/create_users_project.tsx +++ b/src/module/task/ui/create_users_project.tsx @@ -26,7 +26,7 @@ import { globalMemberTask } from "../lib/val_task"; import { FaCheck } from "react-icons/fa6"; import { RiListCheck } from "react-icons/ri"; import { BsListCheck } from "react-icons/bs"; -import { HiMagnifyingGlass } from "react-icons/hi2"; +import { HiChevronLeft, HiMagnifyingGlass } from "react-icons/hi2"; import { IoArrowBackOutline, IoClose } from "react-icons/io5"; import { Carousel } from "@mantine/carousel"; @@ -119,21 +119,27 @@ export default function CreateUsersProject({ onClose }: { onClose: (val: any) => async function fetchGetMember(val: string) { setSearchQuery(val) try { - const res = await funGetSearchMemberDivision('?search=' + val, param.id); - if (res.success) { - setData(res.data) - } else { - toast.error(res.message); - } + const res = await funGetSearchMemberDivision('?search=' + val, param.id); + if (res.success) { + setData(res.data) + } else { + toast.error(res.message); + } } catch (error) { - console.error(error); + console.error(error); } - } + } return ( + { onClose(true) }} bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings"> + + + + } title="Pilih Anggota" menu={ diff --git a/src/module/task/ui/detail_list_file_task.tsx b/src/module/task/ui/detail_list_file_task.tsx index b6ac373..a2e72c4 100644 --- a/src/module/task/ui/detail_list_file_task.tsx +++ b/src/module/task/ui/detail_list_file_task.tsx @@ -18,6 +18,7 @@ export default function ListFileDetailTask() { const [openDrawer, setOpenDrawer] = useState(false) const [isOpenModal, setOpenModal] = useState(false) const [idData, setIdData] = useState('') + const [idDataStorage, setIdDataStorage] = useState('') const [nameStorage, setNameStorage] = useState('') const [nameData, setNameData] = useState('') const [isOpenModalView, setOpenModalView] = useState(false) @@ -52,6 +53,7 @@ export default function ListFileDetailTask() { toast.success(res.message) getOneData() setIdData("") + setIdDataStorage("") setOpenDrawer(false) } else { toast.error(res.message); @@ -102,6 +104,7 @@ export default function ListFileDetailTask() { setExtension(item.extension) setNameStorage(item.nameInStorage) setIdData(item.id) + setIdDataStorage(item.idStorage) setOpenDrawer(true) }} > @@ -167,7 +170,7 @@ export default function ListFileDetailTask() { setOpenModal(false) }} /> - setOpenModalView(false)} file={nameStorage + '.' + isExtension} extension={isExtension} fitur='task' /> + setOpenModalView(false)} file={idDataStorage} extension={isExtension} fitur='task' />
) } \ No newline at end of file