upd: project dan task

Deskripsi:
- tambah project
- perbaiki task

No Issues
This commit is contained in:
amel
2024-08-23 18:10:11 +08:00
parent df2f61e833
commit 5b05edaf38
14 changed files with 163 additions and 115 deletions

View File

@@ -1,21 +1,8 @@
import { import { EditDetailTaskProject } from "@/module/project";
DetailCreateUserProject,
DetailDateEndTask,
EditDetailTaskProject,
FileUploadProgres,
ViewUpdateProgres,
} from "@/module/project";
import React from "react"; import React from "react";
function Page({ searchParams }: { searchParams: any }) { function Page() {
// if (searchParams.page == "upload-progres") return <FileUploadProgres kategori="project" />;
// if (searchParams.page == "detail-create-user")
// return <DetailCreateUserProject kategori="project" />;
// if (searchParams.page == "detail-date-task") return <DetailDateEndTask kategori="project" />;
// return <ViewUpdateProgres searchParams={searchParams} />;
return ( return (
<EditDetailTaskProject/> <EditDetailTaskProject/>
) )

View File

@@ -12,6 +12,8 @@ export async function DELETE(request: Request, context: { params: { id: string }
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
} }
const { id } = context.params; const { id } = context.params;
const { idProject } = (await request.json());
const data = await prisma.projectTask.count({ const data = await prisma.projectTask.count({
where: { where: {
id: id, id: id,
@@ -37,6 +39,35 @@ export async function DELETE(request: Request, context: { params: { id: string }
}, },
}); });
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 updProject = await prisma.project.update({
where: {
id: idProject
},
data: {
status: statusProject
}
})
return NextResponse.json( return NextResponse.json(
{ {
success: true, success: true,
@@ -87,6 +118,8 @@ export async function PUT(request: Request, context: { params: { id: string } })
} }
}) })
// const cek progress
const dataTask = await prisma.projectTask.findMany({ const dataTask = await prisma.projectTask.findMany({
where: { where: {
isActive: true, isActive: true,

View File

@@ -13,6 +13,7 @@ export async function DELETE(request: Request, context: { params: { id: string }
return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
} }
const { id } = context.params; const { id } = context.params;
const { idProject } = (await request.json());
const data = await prisma.divisionProjectTask.count({ const data = await prisma.divisionProjectTask.count({
where: { where: {
id: id, id: id,
@@ -38,6 +39,34 @@ export async function DELETE(request: Request, context: { params: { id: string }
}, },
}); });
// const cek progress
const dataTask = await prisma.divisionProjectTask.findMany({
where: {
isActive: true,
idProject: idProject
}
})
const semua = dataTask.length
const selesai = _.filter(dataTask, { status: 1 }).length
const progress = Math.ceil((selesai / semua) * 100)
let statusProject = 1
if (progress == 100) {
statusProject = 2
} else if (progress == 0) {
statusProject = 0
}
const updProject = await prisma.divisionProject.update({
where: {
id: idProject
},
data: {
status: statusProject
}
})
return NextResponse.json( return NextResponse.json(
{ {
success: true, success: true,

View File

@@ -31,12 +31,13 @@ export const funGetAllMemberById = async (path?: string) => {
} }
export const funDeleteDetailProject = async (path: string) => { export const funDeleteDetailProject = async (path: string, data: { idProject: string }) => {
const response = await fetch(`/api/project/detail/${path}`, { const response = await fetch(`/api/project/detail/${path}`, {
method: "DELETE", method: "DELETE",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
body: JSON.stringify(data),
}); });
return await response.json().catch(() => null); return await response.json().catch(() => null);
} }

View File

@@ -8,7 +8,7 @@ export interface IDataProject {
export interface IDataListTaskProject { export interface IDataListTaskProject {
id: string id: string
name: string title: string
desc: string desc: string
status: number status: number
dateStart: string dateStart: string

View File

@@ -4,7 +4,6 @@ import React, { useState } from 'react';
import { IDataMemberProject, IDataMemberProjectDetail } from '../lib/type_project'; import { IDataMemberProject, IDataMemberProjectDetail } from '../lib/type_project';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
import { funAddMemberProject, funGetAllMemberById, funGetOneProjectById } from '../lib/api_project'; import { funAddMemberProject, funGetAllMemberById, funGetOneProjectById } from '../lib/api_project';
import { funGetDivisionById } from '@/module/division_new';
import { useShallowEffect } from '@mantine/hooks'; import { useShallowEffect } from '@mantine/hooks';
import { Avatar, Box, Button, Divider, Flex, Group, Stack, Text } from '@mantine/core'; import { Avatar, Box, Button, Divider, Flex, Group, Stack, Text } from '@mantine/core';
import { LayoutNavbarNew, WARNA } from '@/module/_global'; import { LayoutNavbarNew, WARNA } from '@/module/_global';
@@ -103,11 +102,9 @@ export default function AddMemberDetailProject() {
<Box> <Box>
<LayoutNavbarNew <LayoutNavbarNew
back="" back=""
title="Pilih Anggotak" title="Pilih Anggota"
menu menu
/> />
<pre>{JSON.stringify(isData, null, 1)}</pre>
<pre>{JSON.stringify(isDataMember, null, 1)}</pre>
<Box p={20}> <Box p={20}>
{/* <TextInput {/* <TextInput
styles={{ styles={{

View File

@@ -46,7 +46,7 @@ export default function EditDetailTaskProject() {
try { try {
const res = await funGetDetailProject(param.id); const res = await funGetDetailProject(param.id);
if (res.success) { if (res.success) {
setName(res.data.name) setName(res.data.title)
setValue([ setValue([
new Date(moment(res.data.dateStart).format('YYYY-MM-DD')), new Date(moment(res.data.dateStart).format('YYYY-MM-DD')),
new Date(moment(res.data.dateEnd).format('YYYY-MM-DD')), new Date(moment(res.data.dateEnd).format('YYYY-MM-DD')),

View File

@@ -40,7 +40,7 @@ export default function EditTaskProject() {
try { try {
const res = await funGetOneProjectById(param.id, 'data'); const res = await funGetOneProjectById(param.id, 'data');
if (res.success) { if (res.success) {
setName(res.data.name); setName(res.data.title);
} else { } else {
toast.error(res.message); toast.error(res.message);
} }
@@ -57,7 +57,7 @@ export default function EditTaskProject() {
return ( return (
<Box> <Box>
<LayoutNavbarNew back="" title={"Edit Judul Tugas"} menu /> <LayoutNavbarNew back="" title={"Edit Judul Proyek"} menu />
<Box p={20}> <Box p={20}>
<Stack pt={15}> <Stack pt={15}>
<Input <Input

View File

@@ -49,12 +49,13 @@ export default function ListTugasDetailProject() {
async function onDelete() { async function onDelete() {
try { try {
const res = await funDeleteDetailProject(idData); const res = await funDeleteDetailProject(idData, { idProject: param.id });
if (res.success) { if (res.success) {
toast.success(res.message); toast.success(res.message);
getOneData(); getOneData();
setIdData("") setIdData("")
setOpenDrawer(false) setOpenDrawer(false)
refresh.set(true)
} else { } else {
toast.error(res.message); toast.error(res.message);
} }
@@ -125,7 +126,7 @@ export default function ListTugasDetailProject() {
> >
<Group> <Group>
<AiOutlineFileSync size={25} /> <AiOutlineFileSync size={25} />
<Text>{item.name}</Text> <Text>{item.title}</Text>
</Group> </Group>
</Box> </Box>
<Box> <Box>
@@ -206,51 +207,51 @@ export default function ListTugasDetailProject() {
</LayoutDrawer> </LayoutDrawer>
<LayoutModal opened={isOpenModal} onClose={() => setOpenModal(false)} <LayoutModal opened={isOpenModal} onClose={() => setOpenModal(false)}
description="Apakah Anda yakin ingin menghapus proyek ini?" description="Apakah Anda yakin ingin menghapus proyek ini?"
onYes={(val) => { onYes={(val) => {
if (val) { if (val) {
onDelete() onDelete()
} }
setOpenModal(false) setOpenModal(false)
}} /> }} />
<LayoutDrawer opened={openDrawerStatus} title={'Status'} onClose={() => setOpenDrawerStatus(false)}>
<Box>
<Stack pt={10}>
{
valStatusDetailProject.map((item, index) => {
return (
<Box mb={5} key={index} onClick={() => { onUpdateStatus(item.value) }}>
<Flex justify={"space-between"} align={"center"}>
<Group>
<Text style={{
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
}}>
{item.name}
</Text>
</Group>
<Text
style={{
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
paddingLeft: 20,
}}
>
{statusData === item.value ? <FaCheck style={{ marginRight: 10 }} /> : ""}
</Text>
</Flex>
<Divider my={"md"} />
</Box>
)
})
}
</Stack> <LayoutDrawer opened={openDrawerStatus} title={'Status'} onClose={() => setOpenDrawerStatus(false)}>
</Box> <Box>
</LayoutDrawer> <Stack pt={10}>
{
valStatusDetailProject.map((item, index) => {
return (
<Box mb={5} key={index} onClick={() => { onUpdateStatus(item.value) }}>
<Flex justify={"space-between"} align={"center"}>
<Group>
<Text style={{
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
}}>
{item.name}
</Text>
</Group>
<Text
style={{
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
paddingLeft: 20,
}}
>
{statusData === item.value ? <FaCheck style={{ marginRight: 10 }} /> : ""}
</Text>
</Flex>
<Divider my={"md"} />
</Box>
)
})
}
</Stack>
</Box>
</LayoutDrawer>
</Box> </Box>
</> </>

View File

@@ -21,7 +21,7 @@ export default function NavbarDetailProject() {
try { try {
const res = await funGetOneProjectById(param.id, 'data'); const res = await funGetOneProjectById(param.id, 'data');
if (res.success) { if (res.success) {
setName(res.data.name); setName(res.data.title);
} else { } else {
toast.error(res.message); toast.error(res.message);
} }

View File

@@ -3,7 +3,7 @@ import { WARNA } from '@/module/_global';
import { useHookstate } from '@hookstate/core'; import { useHookstate } from '@hookstate/core';
import { ActionIcon, Box, Grid, Progress, Text } from '@mantine/core'; import { ActionIcon, Box, Grid, Progress, Text } from '@mantine/core';
import { useParams } from 'next/navigation'; import { useParams } from 'next/navigation';
import React, { useEffect, useState } from 'react'; import React, { useState } from 'react';
import { HiMiniPresentationChartBar } from 'react-icons/hi2'; import { HiMiniPresentationChartBar } from 'react-icons/hi2';
import { globalRefreshProject } from '../lib/val_project'; import { globalRefreshProject } from '../lib/val_project';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
@@ -39,7 +39,7 @@ export default function ProgressDetailProject() {
} }
} }
useEffect(() => { useShallowEffect(() => {
onRefresh() onRefresh()
}, [refresh.get()]) }, [refresh.get()])

View File

@@ -26,12 +26,13 @@ export const funGetTaskDivisionById = async (path: string, kategori: string) =>
} }
export const funDeleteDetailTask = async (path: string) => { export const funDeleteDetailTask = async (path: string, data: { idProject: string }) => {
const response = await fetch(`/api/task/detail/${path}`, { const response = await fetch(`/api/task/detail/${path}`, {
method: "DELETE", method: "DELETE",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
body: JSON.stringify(data),
}); });
return await response.json().catch(() => null); return await response.json().catch(() => null);
}; };

View File

@@ -49,7 +49,7 @@ export default function ListTugasDetailTask() {
async function onDelete() { async function onDelete() {
try { try {
const res = await funDeleteDetailTask(idData); const res = await funDeleteDetailTask(idData, { idProject: param.detail });
if (res.success) { if (res.success) {
toast.success(res.message); toast.success(res.message);
refresh.set(true) refresh.set(true)

View File

@@ -6,7 +6,7 @@ import { useParams } from "next/navigation";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { HiMiniPresentationChartBar } from "react-icons/hi2"; import { HiMiniPresentationChartBar } from "react-icons/hi2";
import { funGetTaskDivisionById } from "../lib/api_task"; import { funGetTaskDivisionById } from "../lib/api_task";
import { useEffect, useState } from "react"; import { useState } from "react";
import { globalRefreshTask } from "../lib/val_task"; import { globalRefreshTask } from "../lib/val_task";
import { useHookstate } from "@hookstate/core"; import { useHookstate } from "@hookstate/core";
@@ -44,8 +44,7 @@ export default function ProgressDetailTask() {
} }
useShallowEffect(() => {
useEffect(() => {
onRefresh() onRefresh()
}, [refresh.get()]) }, [refresh.get()])
@@ -56,44 +55,44 @@ export default function ProgressDetailTask() {
return ( return (
<Box mt={10}> <Box mt={10}>
{loading ? {loading ?
<Skeleton width={"100%"} height={100} radius={"md"} /> <Skeleton width={"100%"} height={100} radius={"md"} />
: :
<Box <Box
p={20} p={20}
bg={"#DCEED8"} bg={"#DCEED8"}
style={{ style={{
borderRadius: 10, borderRadius: 10,
}} }}
> >
<Grid gutter={"lg"}> <Grid gutter={"lg"}>
<Grid.Col span={3}> <Grid.Col span={3}>
<ActionIcon <ActionIcon
variant="gradient" variant="gradient"
size={68} size={68}
aria-label="Gradient action icon" aria-label="Gradient action icon"
radius={100} radius={100}
gradient={{ from: "#DFDA7C", to: "#F2AF46", deg: 174 }} gradient={{ from: "#DFDA7C", to: "#F2AF46", deg: 174 }}
> >
<HiMiniPresentationChartBar size={35} color={WARNA.biruTua} /> <HiMiniPresentationChartBar size={35} color={WARNA.biruTua} />
</ActionIcon> </ActionIcon>
</Grid.Col> </Grid.Col>
<Grid.Col span={9}> <Grid.Col span={9}>
<Box> <Box>
<Text>Kemajuan Proyek {valProgress}%</Text> <Text>Kemajuan Proyek {valProgress}%</Text>
<Progress <Progress
style={{ style={{
border: `1px solid ${"#BDBDBD"}`, border: `1px solid ${"#BDBDBD"}`,
}} }}
w={"100%"} w={"100%"}
color="#FCAA4B" color="#FCAA4B"
radius="md" radius="md"
size="xl" size="xl"
value={valProgress} value={valProgress}
/> />
</Box> </Box>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
</Box> </Box>
} }
</Box> </Box>
) )