upd: project dan task
Deskripsi: - tambah project - perbaiki task No Issues
This commit is contained in:
@@ -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/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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={{
|
||||||
|
|||||||
@@ -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')),
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)}>
|
<LayoutDrawer opened={openDrawerStatus} title={'Status'} onClose={() => setOpenDrawerStatus(false)}>
|
||||||
<Box>
|
<Box>
|
||||||
<Stack pt={10}>
|
<Stack pt={10}>
|
||||||
{
|
{
|
||||||
valStatusDetailProject.map((item, index) => {
|
valStatusDetailProject.map((item, index) => {
|
||||||
return (
|
return (
|
||||||
<Box mb={5} key={index} onClick={() => { onUpdateStatus(item.value) }}>
|
<Box mb={5} key={index} onClick={() => { onUpdateStatus(item.value) }}>
|
||||||
<Flex justify={"space-between"} align={"center"}>
|
<Flex justify={"space-between"} align={"center"}>
|
||||||
<Group>
|
<Group>
|
||||||
<Text style={{
|
<Text style={{
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}}>
|
}}>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
paddingLeft: 20,
|
paddingLeft: 20,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{statusData === item.value ? <FaCheck style={{ marginRight: 10 }} /> : ""}
|
{statusData === item.value ? <FaCheck style={{ marginRight: 10 }} /> : ""}
|
||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Divider my={"md"} />
|
<Divider my={"md"} />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
</LayoutDrawer>
|
</LayoutDrawer>
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()])
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user