diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 28c8827..0062780 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -167,6 +167,7 @@ model Project {
Group Group @relation(fields: [idGroup], references: [id])
idGroup String
name String
+ status Int @default(0) // 0 = pending, 1 = ongoing, 2 = done, 3 = cancelled
desc String @db.Text
isActive Boolean @default(true)
User User @relation(fields: [createdBy], references: [id])
diff --git a/src/app/(application)/project/[id]/page.tsx b/src/app/(application)/project/[id]/page.tsx
index 7ec8b5b..a3143a5 100644
--- a/src/app/(application)/project/[id]/page.tsx
+++ b/src/app/(application)/project/[id]/page.tsx
@@ -1,9 +1,18 @@
-import { ViewDetailProject } from '@/module/project';
+import { LiatAnggotaDetailProject, ListFileDetailProject, ListTugasDetailProject, NavbarDetailProject, ProgressDetailProject, ViewDetailProject } from '@/module/project';
+import { Box } from '@mantine/core';
import React from 'react';
function Page() {
return (
-
+
+
+
+
+
+
+
+
+
);
}
diff --git a/src/app/(application)/project/page.tsx b/src/app/(application)/project/page.tsx
index 8602aa0..6e84723 100644
--- a/src/app/(application)/project/page.tsx
+++ b/src/app/(application)/project/page.tsx
@@ -1,12 +1,12 @@
import { ViewFilter } from '@/module/_global';
-import { ViewProject } from '@/module/project';
+import { TabProject, ViewProject } from '@/module/project';
import React from 'react';
function Page({ searchParams }: { searchParams: { cat: string } }) {
if (searchParams.cat == 'filter')
return
return (
-
+
);
}
diff --git a/src/app/api/project/[id]/route.ts b/src/app/api/project/[id]/route.ts
new file mode 100644
index 0000000..875b6e0
--- /dev/null
+++ b/src/app/api/project/[id]/route.ts
@@ -0,0 +1,41 @@
+import { prisma } from "@/module/_global";
+import { funGetUserByCookies } from "@/module/auth";
+import { NextResponse } from "next/server";
+
+
+// GET ONE PROJECT
+export async function GET(request: Request, context: { params: { id: string } }) {
+ try {
+ const { id } = context.params;
+ const user = await funGetUserByCookies()
+ if (user.id == undefined) {
+ return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
+ }
+
+ const data = await prisma.project.findFirst({
+ where: {
+ id: id
+ },
+ select: {
+ id: true,
+ name: true,
+ desc: true,
+ status: true,
+ ProjectMember: {
+ where: {
+ isActive: true
+ },
+ select: {
+ idUser: true
+ }
+ }
+ }
+ })
+
+ return NextResponse.json({ success: true, message: "Berhasil mendapatkan project", data: data, }, { status: 200 });
+
+ } catch (error) {
+ console.error(error);
+ return NextResponse.json({ success: false, message: "Gagal mendapatkan project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/project/route.ts b/src/app/api/project/route.ts
new file mode 100644
index 0000000..5e42fb0
--- /dev/null
+++ b/src/app/api/project/route.ts
@@ -0,0 +1,65 @@
+import { prisma } from "@/module/_global";
+import { funGetUserByCookies } from "@/module/auth";
+import _ from "lodash";
+import { NextResponse } from "next/server";
+
+
+
+// GET ALL DATA PROJECT
+export async function GET(request: Request) {
+ try {
+ const user = await funGetUserByCookies()
+ if (user.id == undefined) {
+ return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
+ }
+
+ const { searchParams } = new URL(request.url);
+
+ const name = searchParams.get('search');
+ const status = searchParams.get('status');
+ const villageId = user.idVillage
+ const groupId = user.idGroup
+ const userId = user.id
+
+
+ const data = await prisma.project.findMany({
+ where: {
+ isActive: true,
+ idVillage: String(villageId),
+ idGroup: String(groupId),
+ createdBy: String(userId),
+ name: {
+ contains: (name == undefined || name == "null") ? "" : name,
+ mode: "insensitive"
+ },
+ status: (status == "0" || status == "1" || status == "2" || status == "3") ? Number(status) : 0
+ },
+ select: {
+ id: true,
+ name: true,
+ desc: true,
+ status: true,
+ ProjectMember: {
+ where: {
+ isActive: true
+ },
+ select: {
+ idUser: true
+ }
+ }
+ }
+ })
+
+ const omitData = data.map((v: any) => ({
+ ..._.omit(v, ["ProjectMember"]),
+ member: v.ProjectMember.length
+ }))
+
+
+ return NextResponse.json({ success: true, message: "Berhasil mendapatkan project", data: omitData, }, { status: 200 });
+
+ } catch (error) {
+ console.error(error);
+ return NextResponse.json({ success: false, message: "Gagal mendapatkan project, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/module/project/components/detail_project/detail_project.tsx b/src/module/project/components/detail_project/detail_project.tsx
index b7d81f1..eda087d 100644
--- a/src/module/project/components/detail_project/detail_project.tsx
+++ b/src/module/project/components/detail_project/detail_project.tsx
@@ -109,7 +109,6 @@ export default function DetailProject() {
size="xl"
value={60}
/>
- 18 Juni 2024
diff --git a/src/module/project/index.ts b/src/module/project/index.ts
index 4e86bf5..2a20dfb 100644
--- a/src/module/project/index.ts
+++ b/src/module/project/index.ts
@@ -9,6 +9,12 @@ import DetailCreateUserProject from "./components/detail_project/detail_create_u
import DetailDateEndTask from "./components/detail_project/detail_date_end_task";
import DetailFileSave from "./components/detail_project/detail_file_save";
import FileUploadProgres from "./components/detail_project/file_upload_progres";
+import TabProject from "./ui/tab_project";
+import NavbarDetailProject from "./ui/navbar_detail_project";
+import ProgressDetailProject from "./ui/progress_detail_project";
+import ListTugasDetailProject from "./ui/list_tugas_detail_project";
+import ListFileDetailProject from "./ui/list_file_detail_project";
+import LiatAnggotaDetailProject from "./ui/liat_anggota_detail_project";
export { ViewProject }
export { ViewCreateProject }
@@ -20,4 +26,10 @@ export { ViewUpdateProgres }
export { DetailCreateUserProject }
export { DetailDateEndTask }
export { DetailFileSave }
-export { FileUploadProgres }
\ No newline at end of file
+export { FileUploadProgres }
+export { TabProject }
+export { NavbarDetailProject }
+export { ProgressDetailProject }
+export { ListTugasDetailProject }
+export { ListFileDetailProject }
+export { LiatAnggotaDetailProject }
\ No newline at end of file
diff --git a/src/module/project/lib/api_project.ts b/src/module/project/lib/api_project.ts
index e69de29..0761698 100644
--- a/src/module/project/lib/api_project.ts
+++ b/src/module/project/lib/api_project.ts
@@ -0,0 +1,6 @@
+
+
+export const funGetAllProject = async (path?: string) => {
+ const response = await fetch(`/api/project${(path) ? path : ''}`, { next: { tags: ['project'] } });
+ return await response.json().catch(() => null);
+}
\ No newline at end of file
diff --git a/src/module/project/lib/type_project.ts b/src/module/project/lib/type_project.ts
index e69de29..b5e40ab 100644
--- a/src/module/project/lib/type_project.ts
+++ b/src/module/project/lib/type_project.ts
@@ -0,0 +1,7 @@
+export interface IDataProject {
+ id: string
+ name: string
+ desc: string
+ status: number
+ member: number
+ }
\ No newline at end of file
diff --git a/src/module/project/ui/.gitkeep b/src/module/project/ui/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/src/module/project/ui/liat_anggota_detail_project.tsx b/src/module/project/ui/liat_anggota_detail_project.tsx
new file mode 100644
index 0000000..5b4b5a9
--- /dev/null
+++ b/src/module/project/ui/liat_anggota_detail_project.tsx
@@ -0,0 +1,90 @@
+'use client'
+import { WARNA } from '@/module/_global';
+import { Avatar, Box, Flex, Group, Text } from '@mantine/core';
+import React from 'react';
+
+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() {
+ return (
+
+
+ Anggota Terpilih
+ Total 10 Anggota
+
+
+
+
+
+ Divisi Kerohanian
+
+ {dataTugas.map((v, i) => {
+ return (
+
+
+
+
+
+ {v.name}
+
+
+ {v.email}
+
+
+
+
+ Anggota
+
+
+ );
+ })}
+
+
+
+
+ );
+}
+
diff --git a/src/module/project/ui/list_file_detail_project.tsx b/src/module/project/ui/list_file_detail_project.tsx
new file mode 100644
index 0000000..54fc7b6
--- /dev/null
+++ b/src/module/project/ui/list_file_detail_project.tsx
@@ -0,0 +1,22 @@
+'use client'
+import { WARNA } from '@/module/_global';
+import { Box, Text } from '@mantine/core';
+import React from 'react';
+
+export default function ListFileDetailProject() {
+ return (
+ <>
+
+ File
+
+ Tidak ada file
+
+
+ >
+ );
+}
+
diff --git a/src/module/project/ui/list_project.tsx b/src/module/project/ui/list_project.tsx
index 4ab513a..f0569dd 100644
--- a/src/module/project/ui/list_project.tsx
+++ b/src/module/project/ui/list_project.tsx
@@ -1,158 +1,177 @@
"use client"
import { WARNA } from '@/module/_global';
import { ActionIcon, Avatar, Badge, Box, Card, Center, Divider, Flex, Grid, Group, Text, TextInput, Title } from '@mantine/core';
-import { useRouter } from 'next/navigation';
+import { useRouter, useSearchParams } from 'next/navigation';
import React, { useState } from 'react';
import { HiMagnifyingGlass, HiMiniPresentationChartBar, HiOutlineListBullet, HiSquares2X2 } from 'react-icons/hi2';
import { MdAccountCircle } from 'react-icons/md';
import { RiCircleFill } from 'react-icons/ri';
+import { funGetAllProject } from '../lib/api_project';
+import toast from 'react-hot-toast';
+import { useShallowEffect } from '@mantine/hooks';
+import { IDataProject } from '../lib/type_project';
-const dataProject = [
- {
- id: 1,
- title: 'Project 1',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROJECT PROSES',
- },
- {
- id: 2,
- title: 'Project 2',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROJECT PROSES',
- },
- {
- id: 3,
- title: 'Project 3',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROJECT PROSES',
- },
- {
- id: 4,
- title: 'Project 4',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROJECT PROSES',
- },
- {
- id: 5,
- title: 'Project 5',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROJECT PROSES',
- },
- {
- id: 6,
- title: 'Project 6',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROJECT PROSES',
- },
-]
export default function ListProject() {
const [isList, setIsList] = useState(false)
const router = useRouter()
+ const [isData, setData] = useState([])
+ const [loading, setLoading] = useState(true);
+ const searchParams = useSearchParams()
+ const status = searchParams.get('status')
+ const [searchQuery, setSearchQuery] = useState('')
+
+ const fetchData = async () => {
+ try {
+ setData([]);
+ setLoading(true);
+
+ const response = await funGetAllProject('?status=' + status + '&search=' + searchQuery)
+
+ if (response.success) {
+ setData(response?.data)
+ } else {
+ toast.error(response.message);
+ }
+
+ setLoading(false);
+ } catch (error) {
+ toast.error("Gagal mendapatkan proyek, coba lagi nanti");
+ console.error(error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+
+ useShallowEffect(() => {
+ fetchData();
+ }, [status, searchQuery]);
const handleList = () => {
setIsList(!isList)
}
+
return (
-
-
- }
- placeholder="Pencarian"
- />
-
-
-
- {isList ? (
-
- ) : (
-
- )}
-
-
-
-
-
- Total Proyek
-
- 35
-
-
- {isList ? (
-
- {dataProject.map((v, i) => {
- return (
-
- router.push(`/project/${v.id}`)}>
-
-
-
-
-
-
- {v.title}
-
-
-
-
-
-
-
- );
- })}
-
- ) : (
-
- {dataProject.map((v, i) => {
- return (
-
- router.push(`/project/${v.id}`)}>
-
-
-
- {v.title}
-
-
-
-
- {v.description}
-
- {v.status}
-
-
-
-
- +5
-
-
-
-
-
- );
- })}
-
- )}
+
+
+ }
+ placeholder="Pencarian"
+ onChange={(event) => setSearchQuery(event.currentTarget.value)}
+ value={searchQuery}
+ />
+
+
+
+ {isList ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+ Total Proyek
+
+ {isData.length}
+
-
+ {isList ? (
+
+ {isData.map((v, i) => {
+ return (
+
+ router.push(`/project/${v.id}`)}>
+
+
+
+
+
+
+ {v.name}
+
+
+
+
+
+
+
+ );
+ })}
+
+ ) : (
+
+ {isData.map((v, i) => {
+ return (
+
+ router.push(`/project/${v.id}`)}>
+
+
+
+ {v.name}
+
+
+
+
+ {v.desc}
+
+ {
+ v.status === 0 ? 'Segera' :
+ v.status === 1 ? 'Dikerjakan' :
+ v.status === 2 ? 'Selesai' :
+ v.status === 3 ? 'Dibatalkan' :
+ ""
+ }
+
+
+
+
+ +{v.member - 1}
+
+
+
+
+
+ );
+ })}
+
+ )}
+
+
);
}
diff --git a/src/module/project/ui/list_tugas_detail_project.tsx b/src/module/project/ui/list_tugas_detail_project.tsx
new file mode 100644
index 0000000..36f566a
--- /dev/null
+++ b/src/module/project/ui/list_tugas_detail_project.tsx
@@ -0,0 +1,80 @@
+'use client'
+import { WARNA } from '@/module/_global';
+import { Box, Center, Checkbox, Grid, Group, SimpleGrid, Text } from '@mantine/core';
+import React from 'react';
+import { AiOutlineFileSync } from 'react-icons/ai';
+
+export default function ListTugasDetailProject() {
+ return (
+ <>
+
+
+ Tanggal & Tugas
+
+
+
+
+
+
+
+
+
+
+
+
+ Laporan Permasyarakatan
+
+
+
+
+
+ Tanggal Mulai
+
+ 16 Juni 2024
+
+
+
+ Tanggal Berakhir
+
+ 20 Juni 2024
+
+
+
+
+
+
+
+
+ >
+ );
+}
+
diff --git a/src/module/project/ui/navbar_detail_project.tsx b/src/module/project/ui/navbar_detail_project.tsx
new file mode 100644
index 0000000..0236ad5
--- /dev/null
+++ b/src/module/project/ui/navbar_detail_project.tsx
@@ -0,0 +1,104 @@
+'use client'
+import { LayoutDrawer, LayoutNavbarNew, WARNA } from '@/module/_global';
+import { ActionIcon, Box, Flex, SimpleGrid, Stack, Text } from '@mantine/core';
+import { useParams, useRouter } from 'next/navigation';
+import React, { useState } from 'react';
+import { FaPencil, FaUsers } from 'react-icons/fa6';
+import { HiMenu } from 'react-icons/hi';
+import { IoAddCircle } from 'react-icons/io5';
+import { MdCancel } from 'react-icons/md';
+
+export default function NavbarDetailProject() {
+ const router = useRouter()
+ const param = useParams<{ id: string }>()
+ const [name, setName] = useState('')
+ const [isOpen, setOpen] = useState(false)
+ return (
+ <>
+ { setOpen(true) }}
+ >
+
+
+ } />
+
+
+ setOpen(false)}>
+
+
+
+ {
+ router.push(param.id + '/add-task')
+ }}
+ >
+
+
+
+
+ Tambah Tugas
+
+
+
+ {
+ router.push(param.id + '/add-member')
+ }}
+ >
+
+
+
+
+ Tambah anggota
+
+
+
+ { router.push(param.id + '/cancel') }}
+ >
+
+
+
+
+ Batal
+
+
+
+ { router.push(param.id + '/edit') }}
+ >
+
+
+
+
+ Edit
+
+
+
+
+
+
+ >
+ );
+}
+
diff --git a/src/module/project/ui/progress_detail_project.tsx b/src/module/project/ui/progress_detail_project.tsx
new file mode 100644
index 0000000..e2a5551
--- /dev/null
+++ b/src/module/project/ui/progress_detail_project.tsx
@@ -0,0 +1,51 @@
+'use client'
+import { WARNA } from '@/module/_global';
+import { ActionIcon, Box, Grid, Progress, Text } from '@mantine/core';
+import React from 'react';
+import { HiMiniPresentationChartBar } from 'react-icons/hi2';
+
+export default function ProgressDetailProject() {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ Kemajuan Proyek 60%
+
+
+
+
+
+
+ >
+ );
+}
+
diff --git a/src/module/project/ui/tab_project.tsx b/src/module/project/ui/tab_project.tsx
index 04f2f34..0526b8d 100644
--- a/src/module/project/ui/tab_project.tsx
+++ b/src/module/project/ui/tab_project.tsx
@@ -5,8 +5,8 @@ import React, { useEffect, useState } from 'react';
import { HiMenu } from 'react-icons/hi';
import { HiMagnifyingGlass, HiMiniPresentationChartBar, HiOutlineListBullet, HiSquares2X2 } from 'react-icons/hi2';
import { MdAccountCircle } from 'react-icons/md';
-import { RiCircleFill } from "react-icons/ri";
-import { useRouter } from 'next/navigation';
+import { RiCircleFill, RiProgress3Line } from "react-icons/ri";
+import { useRouter, useSearchParams } from 'next/navigation';
import { TbClockPause } from 'react-icons/tb';
import { IoIosCheckmarkCircleOutline } from 'react-icons/io';
import { IoCloseCircleOutline } from 'react-icons/io5';
@@ -15,46 +15,11 @@ import MenuDrawerProject from './menu_drawer_project';
export default function TabProject() {
const [openDrawer, setOpenDrawer] = useState(false)
-
+ const router = useRouter()
+ const searchParams = useSearchParams()
+ const status = searchParams.get('status')
const iconStyle = { width: rem(20), height: rem(20) };
- const tabsData = [
- {
- value: 'segera',
- label: 'Proyek Proses',
- mobileLabel: 'Proses',
- icon: ,
- },
- {
- value: 'selesai',
- label: 'Proyek Selesai',
- mobileLabel: 'Selesai',
- icon: ,
- },
- {
- value: 'batal',
- label: 'Proyek Batal',
- mobileLabel: ' Batal',
- icon: ,
- },
- ];
- const [isMobile, setIsMobile] = useState(false);
-
- useEffect(() => {
- const handleResize = () => {
- if (window.innerWidth < 495) {
- setIsMobile(true);
- } else {
- setIsMobile(false);
- }
- };
- window.addEventListener('resize', handleResize);
- handleResize();
- return () => {
- window.removeEventListener('resize', handleResize);
- };
- }, []);
-
return (
} />
-
+
- {tabsData.map((tab) => (
-
- {isMobile ? tab.mobileLabel : tab.label}
-
- ))}
+ }
+ onClick={() => { router.push("?status=0") }}
+ color={WARNA.biruTua}
+ >
+ Segera
+
+ }
+ onClick={() => { router.push("?status=1") }}
+ color={WARNA.biruTua}
+ >
+ Dikerjakan
+
+ }
+ onClick={() => { router.push("?status=2") }}
+ color={WARNA.biruTua}>
+ Selesai
+
+ }
+ onClick={() => { router.push("?status=3") }}
+ color={WARNA.biruTua}>
+ Batal
+
-
-
-
-
-
-
-
-
-
-
-
-
+
setOpenDrawer(false)}>
-
+
);
diff --git a/src/module/task/ui/list_division_task.tsx b/src/module/task/ui/list_division_task.tsx
index 22ad55f..0979c0f 100644
--- a/src/module/task/ui/list_division_task.tsx
+++ b/src/module/task/ui/list_division_task.tsx
@@ -9,52 +9,6 @@ import { funGetAllTask } from "../lib/api_task";
import toast from "react-hot-toast";
import { useShallowEffect } from "@mantine/hooks";
-
-const dataProject = [
- {
- id: 1,
- title: 'Project 1',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROJECT SELESAI',
- color: '#387529'
- },
- {
- id: 2,
- title: 'Project 2',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROJECT SELESAI',
- color: '#387529'
- },
- {
- id: 3,
- title: 'Project 3',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROJECT SELESAI',
- color: '#387529'
- },
- {
- id: 4,
- title: 'Project 4',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROSES',
- color: '#C5771A'
- },
- {
- id: 5,
- title: 'Project5',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROSES',
- color: '#C5771A'
- },
- {
- id: 6,
- title: 'Project 6',
- description: 'Tempat berkumpul semua anggota / staff perbekal darmasaba',
- status: 'PROSES',
- color: '#C5771A'
- },
-]
-
export default function ListDivisionTask() {
const [isList, setIsList] = useState(false)
const router = useRouter()
diff --git a/src/module/task/ui/navbar_detail_division_task.tsx b/src/module/task/ui/navbar_detail_division_task.tsx
index 450048d..5940198 100644
--- a/src/module/task/ui/navbar_detail_division_task.tsx
+++ b/src/module/task/ui/navbar_detail_division_task.tsx
@@ -122,7 +122,6 @@ export default function NavbarDetailDivisionTask() {
-
>
)
}
\ No newline at end of file