feat : update api project
This commit is contained in:
@@ -168,7 +168,8 @@ model Project {
|
|||||||
idGroup String
|
idGroup String
|
||||||
name String
|
name String
|
||||||
status Int @default(0) // 0 = pending, 1 = ongoing, 2 = done, 3 = cancelled
|
status Int @default(0) // 0 = pending, 1 = ongoing, 2 = done, 3 = cancelled
|
||||||
desc String @db.Text
|
desc String? @db.Text
|
||||||
|
reason String? @db.Text
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
User User @relation(fields: [createdBy], references: [id])
|
User User @relation(fields: [createdBy], references: [id])
|
||||||
createdBy String
|
createdBy String
|
||||||
@@ -177,6 +178,7 @@ model Project {
|
|||||||
ProjectMember ProjectMember[]
|
ProjectMember ProjectMember[]
|
||||||
ProjectFile ProjectFile[]
|
ProjectFile ProjectFile[]
|
||||||
ProjectComment ProjectComment[]
|
ProjectComment ProjectComment[]
|
||||||
|
ProjectTask ProjectTask[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model ProjectMember {
|
model ProjectMember {
|
||||||
@@ -202,6 +204,20 @@ model ProjectFile {
|
|||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model ProjectTask {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
Project Project @relation(fields: [idProject], references: [id])
|
||||||
|
idProject String
|
||||||
|
name String
|
||||||
|
desc String?
|
||||||
|
status Int @default(0) // 0 = pending, 1 = ongoing
|
||||||
|
dateStart DateTime @db.Date
|
||||||
|
dateEnd DateTime @db.Date
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
||||||
|
|
||||||
model ProjectComment {
|
model ProjectComment {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
Project Project @relation(fields: [idProject], references: [id])
|
Project Project @relation(fields: [idProject], references: [id])
|
||||||
|
|||||||
94
src/app/api/project/[id]/member/route.ts
Normal file
94
src/app/api/project/[id]/member/route.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import { prisma } from "@/module/_global";
|
||||||
|
import { funGetUserByCookies } from "@/module/auth";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
|
||||||
|
// ADD MEMBER 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 { member } = (await request.json())
|
||||||
|
|
||||||
|
const data = await prisma.project.count({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data == 0) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false, message: "Gagal mendapatkan project, data tidak ditemukan",
|
||||||
|
},
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (member.length > 0) {
|
||||||
|
const dataMember = member.map((v: any) => ({
|
||||||
|
..._.omit(v, ["idUser", "name"]),
|
||||||
|
idProject: id,
|
||||||
|
idUser: v.idUser
|
||||||
|
}))
|
||||||
|
|
||||||
|
const insertMember = await prisma.projectMember.createMany({
|
||||||
|
data: dataMember
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil menambahkan anggota project" }, { status: 200 });
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal menambah anggota project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MENGELUARKAN ANGGOTA
|
||||||
|
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 { idUser } = (await request.json());
|
||||||
|
|
||||||
|
const data = await prisma.divisionProject.count({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (data == 0) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "Gagal, data tugas tidak ditemukan",
|
||||||
|
},
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteMember = await prisma.projectMember.deleteMany({
|
||||||
|
where: {
|
||||||
|
idProject: id,
|
||||||
|
idUser: idUser
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil mengeluarkan anggota project" }, { status: 200 });
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mengeluarkan anggota project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,41 +1,263 @@
|
|||||||
import { prisma } from "@/module/_global";
|
import { prisma } from "@/module/_global";
|
||||||
import { funGetUserByCookies } from "@/module/auth";
|
import { funGetUserByCookies } from "@/module/auth";
|
||||||
|
import _ from "lodash";
|
||||||
|
import moment from "moment";
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
|
||||||
// GET ONE PROJECT
|
// GET DETAIL PROJECT / GET ONE PROJECT
|
||||||
export async function GET(request: Request, context: { params: { id: string } }) {
|
export async function GET(request: Request, context: { params: { id: string } }) {
|
||||||
try {
|
try {
|
||||||
|
let allData
|
||||||
const { id } = context.params;
|
const { id } = context.params;
|
||||||
const user = await funGetUserByCookies()
|
const user = await funGetUserByCookies()
|
||||||
|
const { searchParams } = new URL(request.url);
|
||||||
|
const kategori = searchParams.get("cat");
|
||||||
|
|
||||||
if (user.id == undefined) {
|
if (user.id == undefined) {
|
||||||
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 data = await prisma.project.findFirst({
|
const data = await prisma.project.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: id
|
id: String(id),
|
||||||
|
isActive: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan project, data tidak ditemukan", }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (kategori == "data") {
|
||||||
|
allData = data
|
||||||
|
} else if (kategori == "progress") {
|
||||||
|
const dataProgress = await prisma.projectTask.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
idProject: String(id)
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
updatedAt: 'desc'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(dataProgress)
|
||||||
|
const semua = dataProgress.length
|
||||||
|
const selesai = _.filter(dataProgress, { status: 1 }).length
|
||||||
|
const progress = Math.ceil((selesai / semua) * 100)
|
||||||
|
|
||||||
|
allData = {
|
||||||
|
progress: progress,
|
||||||
|
lastUpdate: moment(dataProgress[0].updatedAt).format("DD MMMM YYYY"),
|
||||||
|
}
|
||||||
|
} else if (kategori == "task") {
|
||||||
|
const dataProgress = await prisma.projectTask.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
idProject: String(id)
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
name: true,
|
name: true,
|
||||||
desc: true,
|
desc: true,
|
||||||
status: true,
|
status: true,
|
||||||
ProjectMember: {
|
dateStart: true,
|
||||||
|
dateEnd: true,
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
status: 'desc'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const formatData = dataProgress.map((v: any) => ({
|
||||||
|
..._.omit(v, ["dateStart", "dateEnd"]),
|
||||||
|
dateStart: moment(v.dateStart).format("DD MMMM YYYY"),
|
||||||
|
dateEnd: moment(v.dateEnd).format("DD MMMM YYYY"),
|
||||||
|
}))
|
||||||
|
|
||||||
|
allData = formatData
|
||||||
|
|
||||||
|
} else if (kategori == "file") {
|
||||||
|
const dataFile = await prisma.projectFile.findMany({
|
||||||
where: {
|
where: {
|
||||||
isActive: true
|
isActive: true,
|
||||||
|
idProject: String(id)
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
createdAt: 'desc'
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
idUser: true
|
id: true,
|
||||||
|
name: true,
|
||||||
|
extension: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
allData = dataFile
|
||||||
|
} else if (kategori == "member") {
|
||||||
|
|
||||||
|
const dataMember = await prisma.projectMember.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
idProject: String(id)
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
idUser: true,
|
||||||
|
User: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
email: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return NextResponse.json({ success: true, message: "Berhasil mendapatkan project", data: data, }, { status: 200 });
|
const fix = dataMember.map((v: any) => ({
|
||||||
|
..._.omit(v, ["User"]),
|
||||||
|
name: v.User.name,
|
||||||
|
email: v.User.email,
|
||||||
|
}))
|
||||||
|
|
||||||
|
allData = fix
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Berhasil mendapatkan project", data: allData, }, { status: 200 });
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return NextResponse.json({ success: false, message: "Gagal mendapatkan project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
|
return NextResponse.json({ success: false, message: "Gagal mendapatkan project, coba lagi nantiiiiii", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//CREATE NEW DETAIL TASK 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.project.count({
|
||||||
|
where: {
|
||||||
|
id: String(id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data == 0) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false, message: "Gagal mendapatkan project, data tidak ditemukan",
|
||||||
|
},
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataCreate = await prisma.projectTask.create({
|
||||||
|
data: {
|
||||||
|
name,
|
||||||
|
idProject: id,
|
||||||
|
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 ditambahkan", data: dataCreate, }, { status: 200 });
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal tambah detail project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PEMBATALAN TASK PROJECT
|
||||||
|
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 { idTask } = await request.json()
|
||||||
|
const data = await prisma.projectTask.count({
|
||||||
|
where: {
|
||||||
|
id: String(idTask)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data == 0) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false, message: "Gagal mendapatkan project, data tidak ditemukan",
|
||||||
|
},
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataCreate = await prisma.project.update({
|
||||||
|
where: {
|
||||||
|
id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
status: 3,
|
||||||
|
reason: idTask
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Project berhasil dibatalkan" }, { 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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EDIT 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 { name } = await request.json()
|
||||||
|
|
||||||
|
const data = await prisma.project.count({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data == 0) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false, message: "Gagal mendapatkan project, data tidak ditemukan",
|
||||||
|
},
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataCreate = await prisma.project.update({
|
||||||
|
where: {
|
||||||
|
id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, message: "Project berhasil diubah" }, { status: 200 });
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal mengubah project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
54
src/app/api/project/detail/[id]/route.ts
Normal file
54
src/app/api/project/detail/[id]/route.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { prisma } from "@/module/_global";
|
||||||
|
import { funGetUserByCookies } from "@/module/auth";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
|
||||||
|
// HAPUS DETAIL PROJECT
|
||||||
|
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 data = await prisma.projectTask.count({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data == 0) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "Hapus project gagal, data tidak ditemukan",
|
||||||
|
},
|
||||||
|
{ status: 404 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const update = await prisma.projectTask.update({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
isActive: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: true,
|
||||||
|
message: "Project berhasil dihapus",
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return NextResponse.json({ success: false, message: "Gagal menghapus project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// EDIT STATUS DETAIL PROJECT
|
||||||
@@ -4,3 +4,8 @@ export const funGetAllProject = async (path?: string) => {
|
|||||||
const response = await fetch(`/api/project${(path) ? path : ''}`, { next: { tags: ['project'] } });
|
const response = await fetch(`/api/project${(path) ? path : ''}`, { next: { tags: ['project'] } });
|
||||||
return await response.json().catch(() => null);
|
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);
|
||||||
|
}
|
||||||
@@ -4,4 +4,26 @@ export interface IDataProject {
|
|||||||
desc: string
|
desc: string
|
||||||
status: number
|
status: number
|
||||||
member: number
|
member: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IDataListTaskProject {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
desc: string
|
||||||
|
status: number
|
||||||
|
dateStart: string
|
||||||
|
dateEnd: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDataFileProject {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
extension: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDataMemberProject {
|
||||||
|
id: string
|
||||||
|
idUser: string
|
||||||
|
name: string
|
||||||
|
email: string
|
||||||
|
}
|
||||||
3
src/module/project/lib/val_project.ts
Normal file
3
src/module/project/lib/val_project.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { hookstate } from "@hookstate/core";
|
||||||
|
|
||||||
|
export const globalRefreshProject = hookstate<boolean>(false)
|
||||||
@@ -1,47 +1,46 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { WARNA } from '@/module/_global';
|
import { WARNA } from '@/module/_global';
|
||||||
import { Avatar, Box, Flex, Group, Text } from '@mantine/core';
|
import { Avatar, Box, Flex, Group, Text } from '@mantine/core';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import { funGetOneProjectById } from '../lib/api_project';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import { useParams } from 'next/navigation';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IDataMemberProject } from '../lib/type_project';
|
||||||
|
|
||||||
const dataTugas = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: "Iqbal Ramadan",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=5",
|
|
||||||
email: "iqbal.ramadan@gmail.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: "Doni Setiawan",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=10",
|
|
||||||
email: "doni.setiawan@gmail.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: "Rangga Agung",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=51",
|
|
||||||
email: "rangga.agung@gmail.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: "Ramadan Sananta",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=15",
|
|
||||||
email: "ramadan@gmail.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: "Imam Baroni",
|
|
||||||
image: "https://i.pravatar.cc/1000?img=22",
|
|
||||||
email: "imam.baroni@gmail.com",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function LiatAnggotaDetailProject() {
|
export default function LiatAnggotaDetailProject() {
|
||||||
|
const [isData, setData] = useState<IDataMemberProject[]>([])
|
||||||
|
const param = useParams<{ id: string }>()
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
|
async function getOneData() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const res = await funGetOneProjectById(param.id, 'member');
|
||||||
|
if (res.success) {
|
||||||
|
setData(res.data)
|
||||||
|
} else {
|
||||||
|
toast.error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal mendapatkan member proyek, coba lagi nanti");
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getOneData();
|
||||||
|
}, [param.id])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box pt={20}>
|
<Box pt={20}>
|
||||||
<Group justify="space-between">
|
<Group justify="space-between">
|
||||||
<Text c={WARNA.biruTua}>Anggota Terpilih</Text>
|
<Text c={WARNA.biruTua}>Anggota Terpilih</Text>
|
||||||
<Text c={WARNA.biruTua}>Total 10 Anggota</Text>
|
<Text c={WARNA.biruTua}>Total {isData.length} Anggota</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Box pt={10}>
|
<Box pt={10}>
|
||||||
<Box mb={20}>
|
<Box mb={20}>
|
||||||
@@ -53,19 +52,23 @@ export default function LiatAnggotaDetailProject() {
|
|||||||
px={20}
|
px={20}
|
||||||
py={10}
|
py={10}
|
||||||
>
|
>
|
||||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
{
|
||||||
Divisi Kerohanian
|
loading ? <Text>loading</Text> :
|
||||||
</Text>
|
isData.length === 0 ? <Text>Tidak ada anggota</Text> :
|
||||||
{dataTugas.map((v, i) => {
|
isData.map((v, i) => {
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
justify={"space-between"}
|
justify={"space-between"}
|
||||||
align={"center"}
|
align={"center"}
|
||||||
mt={20}
|
mt={20}
|
||||||
key={i}
|
key={i}
|
||||||
|
onClick={() => {
|
||||||
|
// setDataChoose({ id: v.idUser, name: v.name })
|
||||||
|
// setOpenDrawer(true)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Group>
|
<Group>
|
||||||
<Avatar src={v.image} alt="it's me" size="lg" />
|
<Avatar src={""} alt="it's me" size="lg" />
|
||||||
<Box>
|
<Box>
|
||||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||||
{v.name}
|
{v.name}
|
||||||
|
|||||||
@@ -1,9 +1,41 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { WARNA } from '@/module/_global';
|
import { WARNA } from '@/module/_global';
|
||||||
import { Box, Text } from '@mantine/core';
|
import { Box, Group, Text } from '@mantine/core';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import { funGetOneProjectById } from '../lib/api_project';
|
||||||
|
import { useParams } from 'next/navigation';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IDataFileProject } from '../lib/type_project';
|
||||||
|
import { BsFiletypeCsv, BsFiletypeHeic, BsFiletypeJpg, BsFiletypePdf, BsFiletypePng } from 'react-icons/bs';
|
||||||
|
|
||||||
export default function ListFileDetailProject() {
|
export default function ListFileDetailProject() {
|
||||||
|
const [isData, setData] = useState<IDataFileProject[]>([])
|
||||||
|
const param = useParams<{ id: string }>()
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
|
async function getOneData() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const res = await funGetOneProjectById(param.id, 'file');
|
||||||
|
if (res.success) {
|
||||||
|
setData(res.data)
|
||||||
|
} else {
|
||||||
|
toast.error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal mendapatkan file proyek, coba lagi nanti");
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getOneData();
|
||||||
|
}, [param.id])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box pt={20}>
|
<Box pt={20}>
|
||||||
@@ -13,7 +45,33 @@ export default function ListFileDetailProject() {
|
|||||||
border: `1px solid ${"#D6D8F6"}`,
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
padding: 20
|
padding: 20
|
||||||
}}>
|
}}>
|
||||||
<Text>Tidak ada file</Text>
|
{
|
||||||
|
|
||||||
|
loading ? <Text>loading</Text> :
|
||||||
|
isData.length === 0 ? <Text>Tidak ada file</Text> :
|
||||||
|
isData.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
|
padding: 10
|
||||||
|
}}
|
||||||
|
mb={10}
|
||||||
|
>
|
||||||
|
<Group>
|
||||||
|
{item.extension == "pdf" && <BsFiletypePdf size={25} />}
|
||||||
|
{item.extension == "csv" && <BsFiletypeCsv size={25} />}
|
||||||
|
{item.extension == "png" && <BsFiletypePng size={25} />}
|
||||||
|
{item.extension == "jpg" || item.extension == "jpeg" && <BsFiletypeJpg size={25} />}
|
||||||
|
{item.extension == "heic" && <BsFiletypeHeic size={25} />}
|
||||||
|
<Text>{item.name}</Text>
|
||||||
|
</Group>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,10 +1,41 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { WARNA } from '@/module/_global';
|
import { WARNA } from '@/module/_global';
|
||||||
import { Box, Center, Checkbox, Grid, Group, SimpleGrid, Text } from '@mantine/core';
|
import { Box, Center, Checkbox, Divider, Grid, Group, SimpleGrid, Text } from '@mantine/core';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
import { AiOutlineFileSync } from 'react-icons/ai';
|
import { AiOutlineFileSync } from 'react-icons/ai';
|
||||||
|
import { funGetOneProjectById } from '../lib/api_project';
|
||||||
|
import { useParams } from 'next/navigation';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
import { IDataListTaskProject } from '../lib/type_project';
|
||||||
|
|
||||||
export default function ListTugasDetailProject() {
|
export default function ListTugasDetailProject() {
|
||||||
|
const [isData, setData] = useState<IDataListTaskProject[]>([])
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
const param = useParams<{ id: string }>()
|
||||||
|
|
||||||
|
async function getOneData() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const res = await funGetOneProjectById(param.id, 'task');
|
||||||
|
if (res.success) {
|
||||||
|
setData(res.data)
|
||||||
|
} else {
|
||||||
|
toast.error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal mendapatkan list tugas proyek, coba lagi nanti");
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getOneData();
|
||||||
|
}, [param.id])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box pt={20}>
|
<Box pt={20}>
|
||||||
@@ -19,10 +50,22 @@ export default function ListTugasDetailProject() {
|
|||||||
padding: 20,
|
padding: 20,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Grid>
|
{
|
||||||
|
loading ? <Text>loading</Text> :
|
||||||
|
isData.length === 0 ? <Text>Tidak ada tugas</Text> :
|
||||||
|
isData.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Box key={index}>
|
||||||
|
<Grid
|
||||||
|
onClick={() => {
|
||||||
|
// setIdData(item.id)
|
||||||
|
// setStatusData(item.status)
|
||||||
|
// setOpenDrawer(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Grid.Col span={"auto"}>
|
<Grid.Col span={"auto"}>
|
||||||
<Center>
|
<Center>
|
||||||
<Checkbox color="teal" size="md" />
|
<Checkbox color="teal" size="md" checked={(item.status === 1) ? true : false} disabled />
|
||||||
</Center>
|
</Center>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={10}>
|
<Grid.Col span={10}>
|
||||||
@@ -35,7 +78,7 @@ export default function ListTugasDetailProject() {
|
|||||||
>
|
>
|
||||||
<Group>
|
<Group>
|
||||||
<AiOutlineFileSync size={25} />
|
<AiOutlineFileSync size={25} />
|
||||||
<Text>Laporan Permasyarakatan</Text>
|
<Text>{item.name}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
@@ -51,7 +94,7 @@ export default function ListTugasDetailProject() {
|
|||||||
border: `1px solid ${"#D6D8F6"}`,
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text>16 Juni 2024</Text>
|
<Text>{item.dateStart}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
@@ -65,13 +108,18 @@ export default function ListTugasDetailProject() {
|
|||||||
border: `1px solid ${"#D6D8F6"}`,
|
border: `1px solid ${"#D6D8F6"}`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text>20 Juni 2024</Text>
|
<Text>{item.dateEnd}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Box>
|
</Box>
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Divider my={"lg"}/>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,10 +1,53 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { WARNA } from '@/module/_global';
|
import { WARNA } from '@/module/_global';
|
||||||
|
import { useHookstate } from '@hookstate/core';
|
||||||
import { ActionIcon, Box, Grid, Progress, Text } from '@mantine/core';
|
import { ActionIcon, Box, Grid, Progress, Text } from '@mantine/core';
|
||||||
import React from 'react';
|
import { useParams } from 'next/navigation';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
import { HiMiniPresentationChartBar } from 'react-icons/hi2';
|
import { HiMiniPresentationChartBar } from 'react-icons/hi2';
|
||||||
|
import { globalRefreshProject } from '../lib/val_project';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import { funGetOneProjectById } from '../lib/api_project';
|
||||||
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
|
|
||||||
export default function ProgressDetailProject() {
|
export default function ProgressDetailProject() {
|
||||||
|
const [valProgress, setValProgress] = useState(0)
|
||||||
|
const [valLastUpdate, setValLastUpdate] = useState('')
|
||||||
|
const param = useParams<{ id: string }>()
|
||||||
|
const refresh = useHookstate(globalRefreshProject)
|
||||||
|
|
||||||
|
async function getOneData() {
|
||||||
|
try {
|
||||||
|
const res = await funGetOneProjectById(param.id, 'progress');
|
||||||
|
console.log("data",res)
|
||||||
|
if (res.success) {
|
||||||
|
setValProgress(res.data.progress);
|
||||||
|
setValLastUpdate(res.data.lastUpdate);
|
||||||
|
} else {
|
||||||
|
toast.error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal mendapatkan progress proyek, coba lagi nanti");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRefresh() {
|
||||||
|
if (refresh.get()) {
|
||||||
|
getOneData()
|
||||||
|
refresh.set(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onRefresh()
|
||||||
|
}, [refresh.get()])
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
getOneData();
|
||||||
|
}, [param.id])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box mt={10}>
|
<Box mt={10}>
|
||||||
@@ -29,7 +72,7 @@ export default function ProgressDetailProject() {
|
|||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col span={9}>
|
<Grid.Col span={9}>
|
||||||
<Box>
|
<Box>
|
||||||
<Text>Kemajuan Proyek 60%</Text>
|
<Text>Kemajuan Proyek {valProgress}%</Text>
|
||||||
<Progress
|
<Progress
|
||||||
style={{
|
style={{
|
||||||
border: `1px solid ${"#BDBDBD"}`,
|
border: `1px solid ${"#BDBDBD"}`,
|
||||||
@@ -38,7 +81,7 @@ export default function ProgressDetailProject() {
|
|||||||
color="#FCAA4B"
|
color="#FCAA4B"
|
||||||
radius="md"
|
radius="md"
|
||||||
size="xl"
|
size="xl"
|
||||||
value={60}
|
value={valProgress}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
|
|||||||
@@ -103,7 +103,8 @@ export default function ListTugasDetailTask() {
|
|||||||
isData.length === 0 ? <Text>Tidak ada tugas</Text> :
|
isData.length === 0 ? <Text>Tidak ada tugas</Text> :
|
||||||
isData.map((item, index) => {
|
isData.map((item, index) => {
|
||||||
return (
|
return (
|
||||||
<Grid key={index} style={{ borderBottom: "1px solid #D6D8F6" }} pb={10} mb={10}
|
<Box key={index}>
|
||||||
|
<Grid
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIdData(item.id)
|
setIdData(item.id)
|
||||||
setStatusData(item.status)
|
setStatusData(item.status)
|
||||||
@@ -162,6 +163,8 @@ export default function ListTugasDetailTask() {
|
|||||||
</Box>
|
</Box>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Divider my={"lg"} />
|
||||||
|
</Box>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user