From 7c78d974273ef53585398b1aadc37439d1441d4e Mon Sep 17 00:00:00 2001 From: lukman Date: Thu, 22 Aug 2024 15:22:29 +0800 Subject: [PATCH] feat : update project --- .../project/[id]/add-member/page.tsx | 10 + .../project/[id]/add-task/page.tsx | 10 + .../project/[id]/cancel/page.tsx | 10 + .../(application)/project/[id]/edit/page.tsx | 10 + src/app/(application)/project/[id]/page.tsx | 4 +- .../project/update/[id]/page.tsx | 15 +- src/app/api/calender/[id]/route.ts | 4 - src/app/api/project/[id]/member/route.ts | 92 ++++++++- src/app/api/project/[id]/route.ts | 9 +- src/app/api/project/detail/[id]/route.ts | 135 +++++++++++++ src/app/api/project/route.ts | 86 ++++++++ src/module/project/index.ts | 15 +- src/module/project/lib/api_project.ts | 114 +++++++++++ src/module/project/lib/type_project.ts | 50 ++++- src/module/project/lib/val_project.ts | 13 +- .../project/ui/add_detail_task_project.tsx | 133 ++++++++++++ .../project/ui/add_member_detail_project.tsx | 191 ++++++++++++++++++ src/module/project/ui/cancel_project.tsx | 80 ++++++++ .../project/ui/edit_detail_task_project.tsx | 148 ++++++++++++++ src/module/project/ui/edit_task_project.tsx | 102 ++++++++++ .../ui/liat_anggota_detail_project.tsx | 93 --------- .../ui/list_anggota_detail_project.tsx | 155 ++++++++++++++ .../project/ui/list_tugas_detail_project.tsx | 149 +++++++++++++- .../project/ui/navbar_detail_project.tsx | 24 ++- .../project/ui/progress_detail_project.tsx | 1 - src/module/task/ui/add_member_detail_task.tsx | 4 +- 26 files changed, 1526 insertions(+), 131 deletions(-) create mode 100644 src/app/(application)/project/[id]/add-member/page.tsx create mode 100644 src/app/(application)/project/[id]/add-task/page.tsx create mode 100644 src/app/(application)/project/[id]/cancel/page.tsx create mode 100644 src/app/(application)/project/[id]/edit/page.tsx create mode 100644 src/module/project/ui/add_detail_task_project.tsx create mode 100644 src/module/project/ui/add_member_detail_project.tsx create mode 100644 src/module/project/ui/cancel_project.tsx create mode 100644 src/module/project/ui/edit_detail_task_project.tsx create mode 100644 src/module/project/ui/edit_task_project.tsx delete mode 100644 src/module/project/ui/liat_anggota_detail_project.tsx create mode 100644 src/module/project/ui/list_anggota_detail_project.tsx diff --git a/src/app/(application)/project/[id]/add-member/page.tsx b/src/app/(application)/project/[id]/add-member/page.tsx new file mode 100644 index 0000000..fd99420 --- /dev/null +++ b/src/app/(application)/project/[id]/add-member/page.tsx @@ -0,0 +1,10 @@ +import { AddMemberDetailProject } from '@/module/project'; +import React from 'react'; + +function Page() { + return ( + + ); +} + +export default Page; diff --git a/src/app/(application)/project/[id]/add-task/page.tsx b/src/app/(application)/project/[id]/add-task/page.tsx new file mode 100644 index 0000000..246778d --- /dev/null +++ b/src/app/(application)/project/[id]/add-task/page.tsx @@ -0,0 +1,10 @@ +import { AddDetailTaskProject } from '@/module/project'; +import React from 'react'; + +function Page() { + return ( + + ); +} + +export default Page; diff --git a/src/app/(application)/project/[id]/cancel/page.tsx b/src/app/(application)/project/[id]/cancel/page.tsx new file mode 100644 index 0000000..28c0bc9 --- /dev/null +++ b/src/app/(application)/project/[id]/cancel/page.tsx @@ -0,0 +1,10 @@ +import { CancelProject } from '@/module/project'; +import React from 'react'; + +function Page() { + return ( + + ); +} + +export default Page; diff --git a/src/app/(application)/project/[id]/edit/page.tsx b/src/app/(application)/project/[id]/edit/page.tsx new file mode 100644 index 0000000..cde1d7c --- /dev/null +++ b/src/app/(application)/project/[id]/edit/page.tsx @@ -0,0 +1,10 @@ +import { EditTaskProject } from '@/module/project'; +import React from 'react'; + +function Page() { + return ( + + ); +} + +export default Page; diff --git a/src/app/(application)/project/[id]/page.tsx b/src/app/(application)/project/[id]/page.tsx index a3143a5..1153f0c 100644 --- a/src/app/(application)/project/[id]/page.tsx +++ b/src/app/(application)/project/[id]/page.tsx @@ -1,4 +1,4 @@ -import { LiatAnggotaDetailProject, ListFileDetailProject, ListTugasDetailProject, NavbarDetailProject, ProgressDetailProject, ViewDetailProject } from '@/module/project'; +import { ListAnggotaDetailProject, ListFileDetailProject, ListTugasDetailProject, NavbarDetailProject, ProgressDetailProject, ViewDetailProject } from '@/module/project'; import { Box } from '@mantine/core'; import React from 'react'; @@ -10,7 +10,7 @@ function Page() { - + ); diff --git a/src/app/(application)/project/update/[id]/page.tsx b/src/app/(application)/project/update/[id]/page.tsx index e63311a..fb689ee 100644 --- a/src/app/(application)/project/update/[id]/page.tsx +++ b/src/app/(application)/project/update/[id]/page.tsx @@ -1,6 +1,7 @@ import { DetailCreateUserProject, DetailDateEndTask, + EditDetailTaskProject, FileUploadProgres, ViewUpdateProgres, } from "@/module/project"; @@ -8,12 +9,16 @@ import { import React from "react"; function Page({ searchParams }: { searchParams: any }) { - if (searchParams.page == "upload-progres") return ; - if (searchParams.page == "detail-create-user") - return ; - if (searchParams.page == "detail-date-task") return ; + // if (searchParams.page == "upload-progres") return ; + // if (searchParams.page == "detail-create-user") + // return ; + // if (searchParams.page == "detail-date-task") return ; - return ; + // return ; + + return ( + + ) } export default Page; diff --git a/src/app/api/calender/[id]/route.ts b/src/app/api/calender/[id]/route.ts index 14da8c4..d59d363 100644 --- a/src/app/api/calender/[id]/route.ts +++ b/src/app/api/calender/[id]/route.ts @@ -152,7 +152,6 @@ export async function DELETE(request: Request, context: { params: { id: string } export async function PUT(request: Request, context: { params: { id: string } }) { try { - console.log('amalai') const user = await funGetUserByCookies() if (user.id == undefined) { return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); @@ -168,8 +167,6 @@ export async function PUT(request: Request, context: { params: { id: string } }) } }) - console.log(id, title, desc, timeStart, dateStart, timeEnd, linkMeet, repeatEventTyper, member) - if (cek == 0) { return NextResponse.json( { @@ -218,7 +215,6 @@ export async function PUT(request: Request, context: { params: { id: string } }) data: omitMember }); - console.log(omitMember) return NextResponse.json({ success: true, message: "Berhasil mengedit calender" }, { status: 200 }); diff --git a/src/app/api/project/[id]/member/route.ts b/src/app/api/project/[id]/member/route.ts index 71bd20d..ff1ad44 100644 --- a/src/app/api/project/[id]/member/route.ts +++ b/src/app/api/project/[id]/member/route.ts @@ -61,7 +61,7 @@ export async function DELETE(request: Request, context: { params: { id: string } const { id } = context.params const { idUser } = (await request.json()); - const data = await prisma.divisionProject.count({ + const data = await prisma.project.count({ where: { id: id, }, @@ -91,4 +91,94 @@ export async function DELETE(request: Request, context: { params: { id: string } console.error(error); return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); } +} + +//GET MEMBER ALL USER ID GROUP +export async function GET(request: Request, context: { params: { id: string } }) { + try { + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + + const { id } = context.params + const groupId = user.idGroup + const userId = user.id + + const data = await prisma.project.findUnique({ + where: { + id: String(id), + isActive: true + } + }) + + if (data == null) { + return NextResponse.json( + { + success: false, + message: "Gagal, data tugas tidak ditemukan", + }, + { status: 404 } + ); + } + + + // const member = await prisma.projectMember.findMany({ + // where: { + // idProject: String(id), + // isActive: true + // }, + // select: { + // id: true, + // isLeader: true, + // idUser: true, + // User: { + // select: { + // name: true + // } + // } + // }, + // orderBy: { + // isLeader: 'desc', + // } + // }) + + // const fixMember = member.map((v: any) => ({ + // ..._.omit(v, ["User"]), + // name: v.User.name + // })) + + const member = await prisma.user.findMany({ + where: { + idGroup: String(groupId), + id: { + not: String(userId) + }, + isActive: true + }, + select: { + id: true, + name: true, + email: true, + } + }) + + const fixMember = member.map((v: any) => ({ + idUser: v.id, + name: v.name, + email: v.email, + + })) + + const dataFix = { + project: data, + member: fixMember + } + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan project", data: dataFix, }, { status: 200 }); + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } } \ No newline at end of file diff --git a/src/app/api/project/[id]/route.ts b/src/app/api/project/[id]/route.ts index 840b9a1..589c3e0 100644 --- a/src/app/api/project/[id]/route.ts +++ b/src/app/api/project/[id]/route.ts @@ -43,7 +43,6 @@ export async function GET(request: Request, context: { params: { id: string } }) } }) - console.log(dataProgress) const semua = dataProgress.length const selesai = _.filter(dataProgress, { status: 1 }).length const progress = Math.ceil((selesai / semua) * 100) @@ -185,10 +184,10 @@ export async function DELETE(request: Request, context: { params: { id: string } } const { id } = context.params - const { idTask } = await request.json() - const data = await prisma.projectTask.count({ + const { reason } = await request.json() + const data = await prisma.project.count({ where: { - id: String(idTask) + id: id } }) @@ -207,7 +206,7 @@ export async function DELETE(request: Request, context: { params: { id: string } }, data: { status: 3, - reason: idTask + reason: reason } }) diff --git a/src/app/api/project/detail/[id]/route.ts b/src/app/api/project/detail/[id]/route.ts index 25b8b0d..8ca266e 100644 --- a/src/app/api/project/detail/[id]/route.ts +++ b/src/app/api/project/detail/[id]/route.ts @@ -1,5 +1,6 @@ import { prisma } from "@/module/_global"; import { funGetUserByCookies } from "@/module/auth"; +import moment from "moment"; import { NextResponse } from "next/server"; @@ -52,3 +53,137 @@ export async function DELETE(request: Request, context: { params: { id: string } // EDIT STATUS DETAIL PROJECT +export async function PUT(request: Request, context: { params: { id: string } }) { + try { + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + + const { id } = context.params; + const { status, idProject } = (await request.json()); + + const data = await prisma.projectTask.count({ + where: { + id + } + }) + + if (data == 0) { + return NextResponse.json( + { + success: false, message: "Gagal mendapatkan project, data tidak ditemukan", + }, + { status: 404 } + ); + } + + const dataCreate = await prisma.projectTask.update({ + where: { + id + }, + data: { + status: status + } + }) + + const dataTask = await prisma.projectTask.findMany({ + where: { + isActive: true, + idProject: idProject, + } + }) + + const semua = dataTask.length + const selesai = dataTask.filter((item) => item.status == 1).length + const prosess = Math.ceil((selesai / semua) * 100) + let statusProject = 1 + + if (prosess == 100) { + statusProject = 2 + } else if (prosess == 0) { + statusProject = 0 + } + + + const update = await prisma.project.update({ + where: { + id: idProject + }, + data: { + status: statusProject + } + }) + + + return NextResponse.json({ success: true, message: "Status detail Project berhasil diupdate", data }, { status: 200 }); + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal membatalkan project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + + +// GET ONE DETAIL PROJECT +export async function GET(request: Request, context: { params: { id: string } }) { + try { + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + + const { id } = context.params; + const data = await prisma.projectTask.findUnique({ + where: { + id: String(id), + isActive: true + } + }) + + if (!data) { + return NextResponse.json( + { + success: false, message: "Gagal mendapatkan project, data tidak ditemukan", + }, + { status: 404 } + ); + } + + return NextResponse.json({ success: true, message: "Detail project berhasil ditemukan", data }, { status: 200 }); + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + + +// EDIT DETAIL PROJECT +export async function POST(request: Request, context: { params: { id: string } }) { + try { + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + + const { id } = context.params; + const { name, dateStart, dateEnd } = (await request.json()); + + const data = await prisma.projectTask.update({ + where: { + id + }, + data: { + name: name, + dateStart: new Date(moment(dateStart).format('YYYY-MM-DD')), + dateEnd: new Date(moment(dateEnd).format('YYYY-MM-DD')), + } + }) + + return NextResponse.json({ success: true, message: "Detail project berhasil diupdate", data }, { status: 200 }); + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal membatalkan project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/project/route.ts b/src/app/api/project/route.ts index 5e42fb0..7464663 100644 --- a/src/app/api/project/route.ts +++ b/src/app/api/project/route.ts @@ -1,6 +1,7 @@ import { prisma } from "@/module/_global"; import { funGetUserByCookies } from "@/module/auth"; import _ from "lodash"; +import moment from "moment"; import { NextResponse } from "next/server"; @@ -62,4 +63,89 @@ export async function GET(request: Request) { console.error(error); return NextResponse.json({ success: false, message: "Gagal mendapatkan project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); } +} + +// CREATE PROJECT +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 { idVillage, idGroup, name, task, member, file } = (await request.json()) + const userId = user.id + + + const data = await prisma.project.create({ + data: { + idVillage: String(idVillage), + idGroup: String(idGroup), + name: name, + desc: "", + createdBy: String(userId) + }, + select: { + id: true + } + }) + + if (task.length > 0) { + const dataProject = task.map((v: any) => ({ + ..._.omit(v, ["dateStart", "dateEnd", "name"]), + idProject: data.id, + name: v.name, + dateStart: new Date(moment(v.dateStart).format('YYYY-MM-DD')), + dateEnd: new Date(moment(v.dateEnd).format('YYYY-MM-DD')), + })) + + const insertTask = await prisma.projectTask.createMany({ + data: dataProject + }) + } + + if (member.length > 0) { + const dataMember = member.map((v: any) => ({ + ..._.omit(v, ["idUser", "name"]), + idProject: data.id, + idUser: v.idUser, + name: v.name + })) + + const insertMember = await prisma.projectMember.createMany({ + data: dataMember + }) + } + + let fileFix: any[] = [] + + if (file.length > 0) { + file.map((v: any, index: any) => { + const f: any = file[index].get('file') + const fName = f.name + const fExt = fName.split(".").pop() + // funUploadFile(fName, f) + + const dataFile = { + name: fName, + extension: fExt, + idProject: data.id, + } + + fileFix.push(dataFile) + }) + + const insertFile = await prisma.divisionProjectFile.createMany({ + data: fileFix + }) + + } + + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: data, }, { status: 200 }); + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } } \ No newline at end of file diff --git a/src/module/project/index.ts b/src/module/project/index.ts index 2a20dfb..a7c48ee 100644 --- a/src/module/project/index.ts +++ b/src/module/project/index.ts @@ -14,7 +14,13 @@ import NavbarDetailProject from "./ui/navbar_detail_project"; import ProgressDetailProject from "./ui/progress_detail_project"; import ListTugasDetailProject from "./ui/list_tugas_detail_project"; import ListFileDetailProject from "./ui/list_file_detail_project"; -import LiatAnggotaDetailProject from "./ui/liat_anggota_detail_project"; +import LiatAnggotaDetailProject from "./ui/list_anggota_detail_project"; +import EditTaskProject from "./ui/edit_task_project"; +import EditDetailTaskProject from "./ui/edit_detail_task_project"; +import ListAnggotaDetailProject from "./ui/list_anggota_detail_project"; +import AddDetailTaskProject from "./ui/add_detail_task_project"; +import CancelProject from "./ui/cancel_project"; +import AddMemberDetailProject from "./ui/add_member_detail_project"; export { ViewProject } export { ViewCreateProject } @@ -32,4 +38,9 @@ export { NavbarDetailProject } export { ProgressDetailProject } export { ListTugasDetailProject } export { ListFileDetailProject } -export { LiatAnggotaDetailProject } \ No newline at end of file +export { ListAnggotaDetailProject } +export { EditTaskProject } +export { EditDetailTaskProject } +export { AddDetailTaskProject } +export { CancelProject } +export { AddMemberDetailProject } \ No newline at end of file diff --git a/src/module/project/lib/api_project.ts b/src/module/project/lib/api_project.ts index 8716ead..5e2fdfa 100644 --- a/src/module/project/lib/api_project.ts +++ b/src/module/project/lib/api_project.ts @@ -1,3 +1,4 @@ +import { IFormAddDetailproject, IFormAddMemberProject, IFormDateProject, IFormProject } from "./type_project"; export const funGetAllProject = async (path?: string) => { @@ -5,7 +6,120 @@ export const funGetAllProject = async (path?: string) => { return await response.json().catch(() => null); } +export const funCreateProject = async (data: IFormProject) => { + const response = await fetch(`/api/project`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + export const funGetOneProjectById = async (path: string, kategori: string) => { const response = await fetch(`/api/project/${path}?cat=${kategori}`); return await response.json().catch(() => null); +} + +export const funGetAllMemberById = async (path?: string) => { + const response = await fetch(`/api/project/${path}/member`); + return await response.json().catch(() => null); +} + + +export const funDeleteDetailProject = async (path: string) => { + const response = await fetch(`/api/project/detail/${path}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + }); + return await response.json().catch(() => null); +} + + +export const funUpdateStatusProject = async (path: string, data: { status: number, idProject: string }) => { + const response = await fetch(`/api/project/detail/${path}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + + +export const funGetDetailProject = async (path: string) => { + const response = await fetch(`/api/project/detail/${path}`); + return await response.json().catch(() => null); +} + +export const funEditDetailProject = async (path: string, data: IFormDateProject) => { + const response = await fetch(`/api/project/detail/${path}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + + +export const funCreateDetailProject = async (path: string, data: IFormAddDetailproject) => { + const response = await fetch(`/api/project/${path}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + +export const funAddMemberProject = async (path: string, data: IFormAddMemberProject) => { + const response = await fetch(`/api/project/${path}/member`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + + +export const funDeleteMemberProject = async (path: string, data: { idUser: string }) => { + const response = await fetch(`/api/project/${path}/member`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + +export const funCancelProject = async (path: string, data: { reason: string }) => { + const response = await fetch(`/api/project/${path}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + +export const funEditProject = async (path: string, data: { name: string }) => { + const response = await fetch(`/api/project/${path}`, { + 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/project/lib/type_project.ts b/src/module/project/lib/type_project.ts index bad9475..2aa360c 100644 --- a/src/module/project/lib/type_project.ts +++ b/src/module/project/lib/type_project.ts @@ -1,11 +1,11 @@ export interface IDataProject { - id: string - name: string - desc: string - status: number - member: number + id: string + name: string + desc: string + status: number + member: number } - + export interface IDataListTaskProject { id: string name: string @@ -26,4 +26,42 @@ export interface IDataMemberProject { idUser: string name: string email: string +} + +export interface IFormProject { + idDivision: string, + name: string, + task: IFormDateProject[] | [], + member: IFormMemberProject[] | [], + file: FormData[] | [] +} + +export interface IFormDateProject { + dateStart: Date, + dateEnd: Date, + name: string, +} + +export interface IFormMemberProject { + idUser: string, + name: string +} + + +export interface IFormAddDetailproject { + dateStart: Date, + dateEnd: Date, + name: string +} + + +export interface IFormAddMemberProject { + member: IFormMemberProject[] | [] +} + +export interface IDataMemberProjectDetail { + id: string, + idUser: string, + isLeader: string, + name: string } \ No newline at end of file diff --git a/src/module/project/lib/val_project.ts b/src/module/project/lib/val_project.ts index bda7411..bc014c2 100644 --- a/src/module/project/lib/val_project.ts +++ b/src/module/project/lib/val_project.ts @@ -1,3 +1,14 @@ import { hookstate } from "@hookstate/core"; -export const globalRefreshProject = hookstate(false) \ No newline at end of file +export const globalRefreshProject = hookstate(false) + +export const valStatusDetailProject = [ + { + name: "Belum Dikerjakan", + value: 0 + }, + { + name: "Selesai", + value: 1 + } + ] \ No newline at end of file diff --git a/src/module/project/ui/add_detail_task_project.tsx b/src/module/project/ui/add_detail_task_project.tsx new file mode 100644 index 0000000..3f4e5fe --- /dev/null +++ b/src/module/project/ui/add_detail_task_project.tsx @@ -0,0 +1,133 @@ +"use client" +import { useParams, useRouter } from 'next/navigation'; +import React, { useState } from 'react'; +import toast from 'react-hot-toast'; +import { funCreateDetailProject } from '../lib/api_project'; +import { Box, Button, Group, Input, SimpleGrid, Stack, Text } from '@mantine/core'; +import { LayoutNavbarNew, WARNA } from '@/module/_global'; +import { DatePicker } from '@mantine/dates'; +import moment from 'moment'; +import LayoutModal from '@/module/_global/layout/layout_modal'; + +export default function AddDetailTaskProject() { + const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); + const router = useRouter() + const [name, setName] = useState("") + const [openModal, setOpenModal] = useState(false) + const param = useParams<{ id: string }>() + + function onVerification() { + if (value[0] == null || value[1] == null) + return toast.error("Error! harus memilih tanggal") + + if (name == "") + return toast.error("Error! harus memasukkan judul tugas") + + setOpenModal(true) + } + + async function onSubmit() { + try { + const res = await funCreateDetailProject(param.id, { + name, + dateStart: (value[0] != null) ? value[0] : new Date, + dateEnd: (value[1] != null) ? value[1] : new Date, + }) + + if (res.success) { + toast.success(res.message) + setOpenModal(false) + router.push(`/project/${param.id}`) + } else { + toast.error(res.message) + } + } catch (error) { + console.log(error) + toast.error("Gagal menambahkan tugas, coba lagi nanti") + } + } + + return ( + + + + + + + + + Tanggal Mulai + + {value[0] ? `${moment(value[0]).format('DD-MM-YYYY')}` : ""} + + + + Tanggal Berakhir + + {value[1] ? `${moment(value[1]).format('DD-MM-YYYY')}` : ""} + + + + + setName(e.target.value)} + /> + + + + + + + + setOpenModal(false)} + description="Apakah Anda yakin ingin menambahkan tugas?" + onYes={(val) => { + if (val) { + onSubmit() + } + setOpenModal(false) + }} /> + + ); +} + diff --git a/src/module/project/ui/add_member_detail_project.tsx b/src/module/project/ui/add_member_detail_project.tsx new file mode 100644 index 0000000..57477ff --- /dev/null +++ b/src/module/project/ui/add_member_detail_project.tsx @@ -0,0 +1,191 @@ +"use client" +import { useParams, useRouter } from 'next/navigation'; +import React, { useState } from 'react'; +import { IDataMemberProject, IDataMemberProjectDetail } from '../lib/type_project'; +import toast from 'react-hot-toast'; +import { funAddMemberProject, funGetAllMemberById, funGetOneProjectById } from '../lib/api_project'; +import { funGetDivisionById } from '@/module/division_new'; +import { useShallowEffect } from '@mantine/hooks'; +import { Avatar, Box, Button, Divider, Flex, Group, Stack, Text } from '@mantine/core'; +import { LayoutNavbarNew, WARNA } from '@/module/_global'; +import { FaCheck } from 'react-icons/fa6'; +import LayoutModal from '@/module/_global/layout/layout_modal'; + +export default function AddMemberDetailProject() { + const router = useRouter() + const param = useParams<{ id: string }>() + const [selectedFiles, setSelectedFiles] = useState([]) + const [isData, setData] = useState([]) + const [isDataMember, setDataMember] = useState([]) + const [selectAll, setSelectAll] = useState(false) + const [openModal, setOpenModal] = useState(false) + + + async function getData() { + try { + const response = await funGetAllMemberById(param.id) + if (response.success) { + setData(response.data.member) + } else { + toast.error(response.message) + } + + const res = await funGetOneProjectById(param.id, 'member'); + if (res.success) { + setDataMember(res.data) + } else { + toast.error(res.message); + } + } catch (error) { + console.log(error) + toast.error("Gagal mendapatkan anggota, coba lagi nanti"); + } + } + + const handleFileClick = (index: number) => { + if (selectedFiles.some((i: any) => i.idUser == isData[index].idUser)) { + setSelectedFiles(selectedFiles.filter((i: any) => i.idUser != isData[index].idUser)) + } else { + setSelectedFiles([...selectedFiles, { idUser: isData[index].idUser, name: isData[index].name }]) + } + }; + + + + const handleSelectAll = () => { + setSelectAll(!selectAll); + if (!selectAll) { + for (let index = 0; index < isData.length; index++) { + if (!isDataMember.some((i: any) => i.idUser == isData[index].idUser)) { + if (!selectedFiles.some((i: any) => i.idUser == isData[index].idUser)) { + const newArr = { + idUser: isData[index].idUser, name: isData[index].name + } + setSelectedFiles((selectedFiles: any) => [...selectedFiles, newArr]) + } + } + + } + } else { + setSelectedFiles([]); + } + }; + + + function onVerifikasi() { + if (selectedFiles.length == 0) { + return toast.error("Error! silahkan pilih anggota") + } + + setOpenModal(true) + } + + useShallowEffect(() => { + getData() + }, []); + + async function onSubmit() { + try { + const res = await funAddMemberProject(param.id, { member: selectedFiles }); + if (res.success) { + toast.success(res.message) + router.back() + } else { + toast.error(res.message) + } + } catch (error) { + console.log(error) + toast.error("Gagal menambahkan anggota, coba lagi nanti"); + } + } + + return ( + + +
{JSON.stringify(isData, null, 1)}
+
{JSON.stringify(isDataMember, null, 1)}
+ + {/* } + placeholder="Pencarian" + /> */} + + + Pilih Semua Anggota + + {selectAll ? : ""} + + + {isData.map((v, i) => { + const isSelected = selectedFiles.some((i: any) => i?.idUser == v.idUser); + const found = isDataMember.some((i: any) => i.idUser == v.idUser) + return ( + (!found) ? handleFileClick(i) : null}> + + + + + + {v.name} + + {(found) ? "sudah menjadi anggota" : ""} + + + + {isSelected ? : ""} + + + + + ); + })} + + + + + + + setOpenModal(false)} + description="Apakah Anda yakin ingin menambahkan anggota?" + onYes={(val) => { + if (val) { + onSubmit() + } + setOpenModal(false) + }} /> +
+ ); +} diff --git a/src/module/project/ui/cancel_project.tsx b/src/module/project/ui/cancel_project.tsx new file mode 100644 index 0000000..0b0f86a --- /dev/null +++ b/src/module/project/ui/cancel_project.tsx @@ -0,0 +1,80 @@ +"use client" +import { useParams, useRouter } from 'next/navigation'; +import React, { useState } from 'react'; +import toast from 'react-hot-toast'; +import { funCancelProject } from '../lib/api_project'; +import { Box, Button, Stack, Textarea } from '@mantine/core'; +import { LayoutNavbarNew, WARNA } from '@/module/_global'; +import LayoutModal from '@/module/_global/layout/layout_modal'; + +export default function CancelProject() { + const router = useRouter() + const [alasan, setAlasan] = useState("") + const [openModal, setOpenModal] = useState(false) + const param = useParams<{ id: string }>() + + function onVerification() { + if (alasan == "") + return toast.error("Error! harus memasukkan alasan pembatalan proyek") + + setOpenModal(true) + } + + async function onSubmit() { + try { + const res = await funCancelProject(param.id, { reason: alasan }) + if (res.success) { + toast.success(res.message) + router.push("/project") + } else { + toast.error(res.message) + } + } catch (error) { + console.log(error) + toast.error("Gagal membatalkan proyek, coba lagi nanti") + } + } + + return ( + + + + +