From 5e591c69088104615acd6d46cc67dd015312c98f Mon Sep 17 00:00:00 2001 From: amel Date: Mon, 19 Aug 2024 15:15:16 +0800 Subject: [PATCH 1/3] upd: task Deskripsi: - tambah detail task divisi No Issues --- .../task/[detail]/create-task/page.tsx | 9 ++ src/app/api/task/[id]/route.ts | 51 ++++++ src/app/api/task/route.ts | 1 + src/module/task/index.ts | 4 +- src/module/task/lib/api_task.ts | 14 +- src/module/task/lib/type_task.ts | 7 + src/module/task/ui/add_detail_task.tsx | 147 ++++++++++++++++++ .../task/ui/navbar_detail_division_task.tsx | 6 +- 8 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 src/app/(application)/division/[id]/(fitur-division)/task/[detail]/create-task/page.tsx create mode 100644 src/module/task/ui/add_detail_task.tsx diff --git a/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/create-task/page.tsx b/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/create-task/page.tsx new file mode 100644 index 0000000..64459c4 --- /dev/null +++ b/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/create-task/page.tsx @@ -0,0 +1,9 @@ +import { AddDetailTask } from "@/module/task" + +function Page() { + return ( + + ) +} + +export default Page \ No newline at end of file diff --git a/src/app/api/task/[id]/route.ts b/src/app/api/task/[id]/route.ts index 0817ebe..bd5695c 100644 --- a/src/app/api/task/[id]/route.ts +++ b/src/app/api/task/[id]/route.ts @@ -134,4 +134,55 @@ export async function GET(request: Request, context: { params: { id: string } }) console.log(error); return NextResponse.json({ success: false, message: "Gagal mendapatkan tugas divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); } +} + + +// CREATE NEW DETAIL TASK DIVISI +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 { title, dateStart, dateEnd, idDivision } = (await request.json()); + const data = await prisma.divisionProject.count({ + where: { + id: id, + }, + }); + + if (data == 0) { + return NextResponse.json( + { + success: false, + message: "Tambah detail tugas gagal, data tugas tidak ditemukan", + }, + { status: 404 } + ); + } + + const create = await prisma.divisionProjectTask.create({ + data: { + idProject: id, + idDivision, + title, + 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 tugas berhasil ditambahkan", + data, + }, + { status: 200 } + ); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal mengedit detail tugas, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } } \ No newline at end of file diff --git a/src/app/api/task/route.ts b/src/app/api/task/route.ts index 558cabb..7232356 100644 --- a/src/app/api/task/route.ts +++ b/src/app/api/task/route.ts @@ -78,6 +78,7 @@ export async function GET(request: Request) { } +// CREATE PROJECT TASK DIVISION export async function POST(request: Request) { try { const user = await funGetUserByCookies() diff --git a/src/module/task/index.ts b/src/module/task/index.ts index afbcfd7..4882f48 100644 --- a/src/module/task/index.ts +++ b/src/module/task/index.ts @@ -1,3 +1,4 @@ +import AddDetailTask from "./ui/add_detail_task"; import ViewDateEndTask from "./ui/create_date_end_task"; import CreateTask from "./ui/create_task"; import CreateUsersProject from "./ui/create_users_project"; @@ -22,4 +23,5 @@ export { ListTugasDetailTask } export { ProgressDetailTask } export { ListFileDetailTask } export { ListAnggotaDetailTask } -export { EditDetailTask } \ No newline at end of file +export { EditDetailTask } +export { AddDetailTask } \ No newline at end of file diff --git a/src/module/task/lib/api_task.ts b/src/module/task/lib/api_task.ts index 5aec7e2..5811c06 100644 --- a/src/module/task/lib/api_task.ts +++ b/src/module/task/lib/api_task.ts @@ -1,4 +1,4 @@ -import { IFormDateTask, IFormTaskDivision } from "./type_task"; +import { IFormAddDetailTask, IFormDateTask, IFormTaskDivision } from "./type_task"; export const funGetAllTask = async (path?: string) => { const response = await fetch(`/api/task${(path) ? path : ''}`, { next: { tags: ['task'] } }); @@ -64,4 +64,16 @@ export const funEditDetailTask = async (path: string, data: IFormDateTask) => { body: JSON.stringify(data), }); return await response.json().catch(() => null); +}; + + +export const funCreateDetailTask = async (path: string, data: IFormAddDetailTask) => { + const response = await fetch(`/api/task/${path}`, { + method: "POST", + 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/task/lib/type_task.ts b/src/module/task/lib/type_task.ts index 1cfa5bd..4ade39a 100644 --- a/src/module/task/lib/type_task.ts +++ b/src/module/task/lib/type_task.ts @@ -19,6 +19,13 @@ export interface IFormDateTask { title: string } +export interface IFormAddDetailTask { + dateStart: Date, + dateEnd: Date, + title: string + idDivision: string +} + export interface IFormTaskDivision { idDivision: string diff --git a/src/module/task/ui/add_detail_task.tsx b/src/module/task/ui/add_detail_task.tsx new file mode 100644 index 0000000..394ec3b --- /dev/null +++ b/src/module/task/ui/add_detail_task.tsx @@ -0,0 +1,147 @@ +"use client"; +import { LayoutNavbarNew, WARNA } from "@/module/_global"; +import { + Avatar, + Box, + Button, + Flex, + Group, + Input, + SimpleGrid, + Stack, + Text, +} from "@mantine/core"; +import React, { useState } from "react"; +import { DatePicker } from "@mantine/dates"; +import { useParams, useRouter } from "next/navigation"; +import toast from "react-hot-toast"; +import { IFormDateTask } from "../lib/type_task"; +import moment from "moment"; +import { funCreateDetailTask } from "../lib/api_task"; +import LayoutModal from "@/module/_global/layout/layout_modal"; + + +export default function AddDetailTask() { + const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); + const router = useRouter() + const [title, setTitle] = useState("") + const [openModal, setOpenModal] = useState(false) + const param = useParams<{ id: string, detail: string }>() + + function onVerification() { + if (value[0] == null || value[1] == null) + return toast.error("Error! harus memilih tanggal") + + if (title == "") + return toast.error("Error! harus memasukkan judul tugas") + + setOpenModal(true) + } + + async function onSubmit() { + try { + const res = await funCreateDetailTask(param.detail, { + title, + dateStart: (value[0] != null) ? value[0] : new Date, + dateEnd: (value[1] != null) ? value[1] : new Date, + idDivision: param.id + }) + + if (res.success) { + toast.success(res.message) + setOpenModal(false) + router.push(`/division/${param.id}/task/${param.detail}`) + } 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')}` : ""} + + + + + setTitle(e.target.value)} + /> + + + + + + + + setOpenModal(false)} + description="Apakah Anda yakin ingin menambahkan tugas?" + onYes={(val) => { + if (val) { + onSubmit() + } + setOpenModal(false) + }} /> + + ); +} diff --git a/src/module/task/ui/navbar_detail_division_task.tsx b/src/module/task/ui/navbar_detail_division_task.tsx index 6e39331..bde2b08 100644 --- a/src/module/task/ui/navbar_detail_division_task.tsx +++ b/src/module/task/ui/navbar_detail_division_task.tsx @@ -45,7 +45,7 @@ export default function NavbarDetailDivisionTask() { size="lg" radius="lg" aria-label="Settings" - onClick={() => { }} + onClick={() => { setOpen(true) }} > @@ -63,14 +63,14 @@ export default function NavbarDetailDivisionTask() { cursor: 'pointer' }} onClick={() => { - router.push('/announcement/create') + router.push(param.detail + '/create-task') }} > - Tambah Pengumuman + Tambah Tugas From 912f4fd3099bc6a5d28a9ea67805711b4d960f48 Mon Sep 17 00:00:00 2001 From: amel Date: Mon, 19 Aug 2024 16:11:20 +0800 Subject: [PATCH 2/3] upd: tambah anggota task Deskripsi: -tambah anggota task NO ISsues --- .../task/[detail]/add-member/page.tsx | 9 + .../{create-task => add-task}/page.tsx | 0 src/app/api/task/[id]/member/route.ts | 61 ++++++ src/app/api/task/[id]/route.ts | 4 +- src/module/task/index.ts | 4 +- src/module/task/lib/api_task.ts | 13 +- src/module/task/lib/type_task.ts | 7 + src/module/task/ui/add_member_detail_task.tsx | 203 ++++++++++++++++++ src/module/task/ui/create_task.tsx | 1 - .../task/ui/navbar_detail_division_task.tsx | 9 +- 10 files changed, 303 insertions(+), 8 deletions(-) create mode 100644 src/app/(application)/division/[id]/(fitur-division)/task/[detail]/add-member/page.tsx rename src/app/(application)/division/[id]/(fitur-division)/task/[detail]/{create-task => add-task}/page.tsx (100%) create mode 100644 src/app/api/task/[id]/member/route.ts create mode 100644 src/module/task/ui/add_member_detail_task.tsx diff --git a/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/add-member/page.tsx b/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/add-member/page.tsx new file mode 100644 index 0000000..9f9852e --- /dev/null +++ b/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/add-member/page.tsx @@ -0,0 +1,9 @@ +import { AddMemberDetailTask } from "@/module/task" + +function Page() { + return ( + + ) +} + +export default Page \ No newline at end of file diff --git a/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/create-task/page.tsx b/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/add-task/page.tsx similarity index 100% rename from src/app/(application)/division/[id]/(fitur-division)/task/[detail]/create-task/page.tsx rename to src/app/(application)/division/[id]/(fitur-division)/task/[detail]/add-task/page.tsx diff --git a/src/app/api/task/[id]/member/route.ts b/src/app/api/task/[id]/member/route.ts new file mode 100644 index 0000000..02e96e2 --- /dev/null +++ b/src/app/api/task/[id]/member/route.ts @@ -0,0 +1,61 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import _ from "lodash"; +import moment from "moment"; +import { NextResponse } from "next/server"; + +// ADD MEMBER TASK DIVISI +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 { member, idDivision } = (await request.json()); + + const data = await prisma.divisionProject.count({ + where: { + id: id, + }, + }); + + console.log(member, idDivision) + + if (data == 0) { + return NextResponse.json( + { + success: false, + message: "Tambah anggota tugas gagal, data tugas tidak ditemukan", + }, + { status: 404 } + ); + } + + if (member.length > 0) { + const dataMember = member.map((v: any) => ({ + ..._.omit(v, ["idUser", "name"]), + idDivision: idDivision, + idProject: id, + idUser: v.idUser, + })) + + const insertMember = await prisma.divisionProjectMember.createMany({ + data: dataMember + }) + } + + + return NextResponse.json( + { + success: true, + message: "Berhasil menambahkan anggota tugas", + }, + { status: 200 } + ); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal menambah anggota tugas, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/task/[id]/route.ts b/src/app/api/task/[id]/route.ts index bd5695c..48d7fed 100644 --- a/src/app/api/task/[id]/route.ts +++ b/src/app/api/task/[id]/route.ts @@ -108,6 +108,7 @@ export async function GET(request: Request, context: { params: { id: string } }) }, select: { id: true, + idUser: true, User: { select: { name: true, @@ -185,4 +186,5 @@ export async function POST(request: Request, context: { params: { id: string } } console.log(error); return NextResponse.json({ success: false, message: "Gagal mengedit detail tugas, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); } -} \ No newline at end of file +} + diff --git a/src/module/task/index.ts b/src/module/task/index.ts index 4882f48..35c1726 100644 --- a/src/module/task/index.ts +++ b/src/module/task/index.ts @@ -1,4 +1,5 @@ import AddDetailTask from "./ui/add_detail_task"; +import AddMemberDetailTask from "./ui/add_member_detail_task"; import ViewDateEndTask from "./ui/create_date_end_task"; import CreateTask from "./ui/create_task"; import CreateUsersProject from "./ui/create_users_project"; @@ -24,4 +25,5 @@ export { ProgressDetailTask } export { ListFileDetailTask } export { ListAnggotaDetailTask } export { EditDetailTask } -export { AddDetailTask } \ No newline at end of file +export { AddDetailTask } +export { AddMemberDetailTask } \ No newline at end of file diff --git a/src/module/task/lib/api_task.ts b/src/module/task/lib/api_task.ts index 5811c06..197b274 100644 --- a/src/module/task/lib/api_task.ts +++ b/src/module/task/lib/api_task.ts @@ -1,4 +1,4 @@ -import { IFormAddDetailTask, IFormDateTask, IFormTaskDivision } from "./type_task"; +import { IFormAddDetailTask, IFormAddMemberTask, IFormDateTask, IFormTaskDivision } from "./type_task"; export const funGetAllTask = async (path?: string) => { const response = await fetch(`/api/task${(path) ? path : ''}`, { next: { tags: ['task'] } }); @@ -76,4 +76,15 @@ export const funCreateDetailTask = async (path: string, data: IFormAddDetailTask body: JSON.stringify(data), }); return await response.json().catch(() => null); +}; + +export const funAddMemberTask = async (path: string, data: IFormAddMemberTask) => { + const response = await fetch(`/api/task/${path}/member`, { + method: "POST", + 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/task/lib/type_task.ts b/src/module/task/lib/type_task.ts index 4ade39a..6c89dce 100644 --- a/src/module/task/lib/type_task.ts +++ b/src/module/task/lib/type_task.ts @@ -27,6 +27,12 @@ export interface IFormAddDetailTask { } +export interface IFormAddMemberTask { + idDivision: string + member: IFormMemberTask[] | [] +} + + export interface IFormTaskDivision { idDivision: string title: string @@ -51,6 +57,7 @@ export interface IDataListTaskDivision { export interface IDataMemberTaskDivision { id: string + idUser: string name: string email: string } diff --git a/src/module/task/ui/add_member_detail_task.tsx b/src/module/task/ui/add_member_detail_task.tsx new file mode 100644 index 0000000..aa85df3 --- /dev/null +++ b/src/module/task/ui/add_member_detail_task.tsx @@ -0,0 +1,203 @@ +"use client" +import { LayoutNavbarNew, WARNA } from "@/module/_global"; +import { funGetDivisionById, IDataMemberDivision } from "@/module/division_new"; +import { + Anchor, + Avatar, + Box, + Button, + Checkbox, + Divider, + Flex, + Group, + Stack, + Text, + TextInput, +} from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { useParams, useRouter } from "next/navigation"; +import React, { useState } from "react"; +import toast from "react-hot-toast"; +import { FaCheck } from "react-icons/fa6"; +import { funAddMemberTask, funGetTaskDivisionById } from "../lib/api_task"; +import { IDataMemberTaskDivision } from "../lib/type_task"; +import LayoutModal from "@/module/_global/layout/layout_modal"; + +export default function AddMemberDetailTask() { + const router = useRouter() + const param = useParams<{ id: string, detail: 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 funGetDivisionById(param.id) + if (response.success) { + setData(response.data.member) + } else { + toast.error(response.message) + } + + const res = await funGetTaskDivisionById(param.detail, '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"); + } + } + + + useShallowEffect(() => { + getData() + }, []); + + 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) + } + + async function onSubmit() { + try { + const res = await funAddMemberTask(param.detail, { idDivision: 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 ( + + + + {/* } + 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/task/ui/create_task.tsx b/src/module/task/ui/create_task.tsx index dd20f0b..cbd4382 100644 --- a/src/module/task/ui/create_task.tsx +++ b/src/module/task/ui/create_task.tsx @@ -52,7 +52,6 @@ export default function CreateTask() { async function onSubmit() { try { - console.log("kirim",fileForm) const response = await funCreateTask({ idDivision: param.id, title, task: dataTask, file: fileForm, member: memberValue }) if (response.success) { diff --git a/src/module/task/ui/navbar_detail_division_task.tsx b/src/module/task/ui/navbar_detail_division_task.tsx index bde2b08..d3076f0 100644 --- a/src/module/task/ui/navbar_detail_division_task.tsx +++ b/src/module/task/ui/navbar_detail_division_task.tsx @@ -9,6 +9,7 @@ import { useShallowEffect } from "@mantine/hooks"; import { HiMenu } from "react-icons/hi"; import { IoAddCircle } from "react-icons/io5"; import { RiFilter2Line } from "react-icons/ri"; +import { FaUsers } from "react-icons/fa6"; export default function NavbarDetailDivisionTask() { const router = useRouter() @@ -63,7 +64,7 @@ export default function NavbarDetailDivisionTask() { cursor: 'pointer' }} onClick={() => { - router.push(param.detail + '/create-task') + router.push(param.detail + '/add-task') }} > @@ -79,14 +80,14 @@ export default function NavbarDetailDivisionTask() { cursor: 'pointer' }} onClick={() => { - router.push('/announcement?page=filter') + router.push(param.detail + '/add-member') }} > - + - Filter + Tambah anggota From a0155677f6ca3dbb1850ee5f43e95ed329611ec4 Mon Sep 17 00:00:00 2001 From: amel Date: Mon, 19 Aug 2024 17:38:30 +0800 Subject: [PATCH 3/3] upd: task divisi Deskripsi: - cancel task - edit title task No Issues --- prisma/schema.prisma | 3 +- .../task/[detail]/cancel/page.tsx | 9 ++ .../task/[detail]/edit/page.tsx | 9 ++ src/app/api/task/[id]/route.ts | 100 ++++++++++++++++ src/module/task/index.ts | 6 +- src/module/task/lib/api_task.ts | 25 ++++ src/module/task/ui/cancel_task.tsx | 87 ++++++++++++++ src/module/task/ui/edit_task.tsx | 110 ++++++++++++++++++ .../task/ui/navbar_detail_division_task.tsx | 33 +++++- 9 files changed, 378 insertions(+), 4 deletions(-) create mode 100644 src/app/(application)/division/[id]/(fitur-division)/task/[detail]/cancel/page.tsx create mode 100644 src/app/(application)/division/[id]/(fitur-division)/task/[detail]/edit/page.tsx create mode 100644 src/module/task/ui/cancel_task.tsx create mode 100644 src/module/task/ui/edit_task.tsx diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3ccc229..28c8827 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -257,7 +257,8 @@ model DivisionProject { Division Division @relation(fields: [idDivision], references: [id]) idDivision String title String - desc String @db.Text + desc String? @db.Text + reason String? @db.Text status Int @default(0) // 0 = pending, 1 = ongoing, 2 = done, 3 = cancelled isActive Boolean @default(true) createdAt DateTime @default(now()) diff --git a/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/cancel/page.tsx b/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/cancel/page.tsx new file mode 100644 index 0000000..e63ee85 --- /dev/null +++ b/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/cancel/page.tsx @@ -0,0 +1,9 @@ +import { CancelTask } from "@/module/task" + +function Page() { + return ( + + ) +} + +export default Page \ No newline at end of file diff --git a/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/edit/page.tsx b/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/edit/page.tsx new file mode 100644 index 0000000..290ecb6 --- /dev/null +++ b/src/app/(application)/division/[id]/(fitur-division)/task/[detail]/edit/page.tsx @@ -0,0 +1,9 @@ +import { EditTask } from "@/module/task" + +function Page() { + return ( + + ) +} + +export default Page \ No newline at end of file diff --git a/src/app/api/task/[id]/route.ts b/src/app/api/task/[id]/route.ts index 48d7fed..b68849f 100644 --- a/src/app/api/task/[id]/route.ts +++ b/src/app/api/task/[id]/route.ts @@ -188,3 +188,103 @@ export async function POST(request: Request, context: { params: { id: string } } } } + + +// PEMBATALAN TASK DIVISI +export async function DELETE(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 { reason } = (await request.json()); + const data = await prisma.divisionProject.count({ + where: { + id: id, + }, + }); + + if (data == 0) { + return NextResponse.json( + { + success: false, + message: "Pembatalan tugas gagal, data tugas tidak ditemukan", + }, + { status: 404 } + ); + } + + const update = await prisma.divisionProject.update({ + where: { + id + }, + data: { + reason: reason, + status: 3 + } + }); + + return NextResponse.json( + { + success: true, + message: "Tugas berhasil dibatalkan", + }, + { status: 200 } + ); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal membatalkan tugas, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + + +// EDIT TASK DIVISI +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 { title } = (await request.json()); + const data = await prisma.divisionProject.count({ + where: { + id: id, + }, + }); + + if (data == 0) { + return NextResponse.json( + { + success: false, + message: "Tugas gagal diedit, data tugas tidak ditemukan", + }, + { status: 404 } + ); + } + + const update = await prisma.divisionProject.update({ + where: { + id + }, + data: { + title + } + }); + + return NextResponse.json( + { + success: true, + message: "Tugas berhasil diedit", + }, + { status: 200 } + ); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal mengedit tugas, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + diff --git a/src/module/task/index.ts b/src/module/task/index.ts index 35c1726..159e6b9 100644 --- a/src/module/task/index.ts +++ b/src/module/task/index.ts @@ -1,5 +1,6 @@ import AddDetailTask from "./ui/add_detail_task"; import AddMemberDetailTask from "./ui/add_member_detail_task"; +import CancelTask from "./ui/cancel_task"; import ViewDateEndTask from "./ui/create_date_end_task"; import CreateTask from "./ui/create_task"; import CreateUsersProject from "./ui/create_users_project"; @@ -8,6 +9,7 @@ import ListFileDetailTask from "./ui/detail_list_file_task"; import ListTugasDetailTask from "./ui/detail_list_tugas_task"; import ProgressDetailTask from "./ui/detail_progress_task"; import EditDetailTask from "./ui/edit_detail_task"; +import EditTask from "./ui/edit_task"; import FileSave from "./ui/file_save"; import NavbarDetailDivisionTask from "./ui/navbar_detail_division_task"; import NavbarDivisionTask from "./ui/navbar_division_task"; @@ -26,4 +28,6 @@ export { ListFileDetailTask } export { ListAnggotaDetailTask } export { EditDetailTask } export { AddDetailTask } -export { AddMemberDetailTask } \ No newline at end of file +export { AddMemberDetailTask } +export { CancelTask } +export { EditTask } \ No newline at end of file diff --git a/src/module/task/lib/api_task.ts b/src/module/task/lib/api_task.ts index 197b274..959fe28 100644 --- a/src/module/task/lib/api_task.ts +++ b/src/module/task/lib/api_task.ts @@ -87,4 +87,29 @@ export const funAddMemberTask = async (path: string, data: IFormAddMemberTask) = body: JSON.stringify(data), }); return await response.json().catch(() => null); +}; + + +export const funCancelTask = async (path: string, data: { reason: string }) => { + const response = await fetch(`/api/task/${path}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +}; + + + +export const funEditTask = async (path: string, data: { title: string }) => { + const response = await fetch(`/api/task/${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/task/ui/cancel_task.tsx b/src/module/task/ui/cancel_task.tsx new file mode 100644 index 0000000..1e0b4db --- /dev/null +++ b/src/module/task/ui/cancel_task.tsx @@ -0,0 +1,87 @@ +"use client"; +import { LayoutNavbarNew, WARNA } from "@/module/_global"; +import { + Box, + Button, + Stack, + Textarea, +} from "@mantine/core"; +import React, { useState } from "react"; +import { useParams, useRouter } from "next/navigation"; +import toast from "react-hot-toast"; +import { funCancelTask } from "../lib/api_task"; +import LayoutModal from "@/module/_global/layout/layout_modal"; + + +export default function CancelTask() { + const router = useRouter() + const [alasan, setAlasan] = useState("") + const [openModal, setOpenModal] = useState(false) + const param = useParams<{ id: string, detail: string }>() + + function onVerification() { + if (alasan == "") + return toast.error("Error! harus memasukkan alasan pembatalan tugas") + + setOpenModal(true) + } + + async function onSubmit() { + try { + const res = await funCancelTask(param.detail, { reason: alasan }) + if (res.success) { + toast.success(res.message) + router.push("./") + } else { + toast.error(res.message) + } + } catch (error) { + console.log(error) + toast.error("Gagal membatalkan tugas, coba lagi nanti") + } + } + + + + return ( + + + + +