From f0c708a8f3f2b7f89c6517fe9121aea04a7e5e69 Mon Sep 17 00:00:00 2001 From: amel Date: Fri, 9 Aug 2024 17:25:02 +0800 Subject: [PATCH] fitur: divisi Deskripsi: - pengaplikasian api terbaru pada divisi - list divisi - create divisi - detail divisi No Issues --- src/app/(application)/division/[id]/page.tsx | 16 +- .../(application)/division/create/page.tsx | 10 +- src/app/(application)/division/page.tsx | 5 +- src/app/api/division/[id]/detail/route.ts | 157 ++++++++++++++++++ src/app/api/division/[id]/route.ts | 32 ++++ src/app/api/division/route.ts | 114 +++++++++++++ .../carousel_division.tsx | 0 .../components/create_admin_division.tsx | 2 +- .../components/create_division.tsx | 7 +- .../division_new/components/create_users.tsx | 2 +- .../detail_division/detail_division.tsx | 27 --- .../detail_division/list_document.tsx | 69 -------- .../components/detail_division/list_task.tsx | 66 -------- .../{ui => }/drawer_detail_division.tsx | 0 .../components/{ui => }/drawer_division.tsx | 0 .../feature_detail_division.tsx | 48 ++++-- .../{detail_division => }/list_discussion.tsx | 60 ++++++- .../navbar_division.tsx => list_division.tsx} | 53 +++--- .../division_new/components/list_document.tsx | 86 ++++++++++ .../division_new/components/list_task.tsx | 89 ++++++++++ .../{ui => }/navbar_admin_division.tsx | 60 ++++--- .../{ui => }/navbar_create_users.tsx | 39 +---- .../components/navbar_detail_division.tsx | 50 ++++++ .../components/ui/navbar_detail_division.tsx | 24 --- src/module/division_new/index.ts | 24 ++- src/module/division_new/lib/api_division.ts | 27 +++ src/module/division_new/lib/type_division.ts | 50 ++++++ src/module/division_new/lib/val_division.ts | 4 +- .../view/view_create_division.tsx | 8 - .../view/view_detail_division.tsx | 35 ---- .../division_new/view/view_division.tsx | 9 - src/module/group/ui/edit_drawer_group.tsx | 1 - 32 files changed, 821 insertions(+), 353 deletions(-) create mode 100644 src/app/api/division/[id]/detail/route.ts create mode 100644 src/app/api/division/[id]/route.ts create mode 100644 src/app/api/division/route.ts rename src/module/division_new/components/{detail_division => }/carousel_division.tsx (100%) delete mode 100644 src/module/division_new/components/detail_division/detail_division.tsx delete mode 100644 src/module/division_new/components/detail_division/list_document.tsx delete mode 100644 src/module/division_new/components/detail_division/list_task.tsx rename src/module/division_new/components/{ui => }/drawer_detail_division.tsx (100%) rename src/module/division_new/components/{ui => }/drawer_division.tsx (100%) rename src/module/division_new/components/{detail_division => }/feature_detail_division.tsx (75%) rename src/module/division_new/components/{detail_division => }/list_discussion.tsx (53%) rename src/module/division_new/components/{ui/navbar_division.tsx => list_division.tsx} (82%) create mode 100644 src/module/division_new/components/list_document.tsx create mode 100644 src/module/division_new/components/list_task.tsx rename src/module/division_new/components/{ui => }/navbar_admin_division.tsx (67%) rename src/module/division_new/components/{ui => }/navbar_create_users.tsx (83%) create mode 100644 src/module/division_new/components/navbar_detail_division.tsx delete mode 100644 src/module/division_new/components/ui/navbar_detail_division.tsx create mode 100644 src/module/division_new/lib/api_division.ts create mode 100644 src/module/division_new/lib/type_division.ts delete mode 100644 src/module/division_new/view/view_create_division.tsx delete mode 100644 src/module/division_new/view/view_detail_division.tsx delete mode 100644 src/module/division_new/view/view_division.tsx diff --git a/src/app/(application)/division/[id]/page.tsx b/src/app/(application)/division/[id]/page.tsx index 9ba7527..044105b 100644 --- a/src/app/(application)/division/[id]/page.tsx +++ b/src/app/(application)/division/[id]/page.tsx @@ -1,9 +1,21 @@ -import { ViewDetailDivision } from '@/module/division_new'; +import { NavbarDetailDivision, CarouselDivision, FeatureDetailDivision, ListTaskOnDetailDivision, ListDocumentOnDetailDivision, ListDiscussionOnDetailDivision } from '@/module/division_new'; +import { Box, Stack } from '@mantine/core'; import React from 'react'; function Page({ params }: { params: { id: string } }) { return ( - + + + + + + + + + + + + ); } diff --git a/src/app/(application)/division/create/page.tsx b/src/app/(application)/division/create/page.tsx index 1f4bd3b..ea41ae0 100644 --- a/src/app/(application)/division/create/page.tsx +++ b/src/app/(application)/division/create/page.tsx @@ -1,13 +1,9 @@ -import { CreateAdminDivision, CreateUsers, ViewCreateDivision } from '@/module/division_new'; +import { CreateDivision } from '@/module/division_new'; import React from 'react'; -function Page({ searchParams }: { searchParams: { page: string } }) { - // if (searchParams.page == "anggota") - // return - // if (searchParams.page == "pilih-admin") - // return +function Page() { return ( - + ); } diff --git a/src/app/(application)/division/page.tsx b/src/app/(application)/division/page.tsx index 0db2af4..acbd0f7 100644 --- a/src/app/(application)/division/page.tsx +++ b/src/app/(application)/division/page.tsx @@ -1,6 +1,5 @@ - import { ViewFilter } from '@/module/_global'; -import { ViewCreateReport, ViewDivision } from '@/module/division_new'; +import { ListDivision, ViewCreateReport } from '@/module/division_new'; import React from 'react'; function Page({ searchParams }: { searchParams: { page: string } }) { @@ -9,7 +8,7 @@ function Page({ searchParams }: { searchParams: { page: string } }) { if (searchParams.page == "report") return return ( - + ); } diff --git a/src/app/api/division/[id]/detail/route.ts b/src/app/api/division/[id]/detail/route.ts new file mode 100644 index 0000000..1269a5c --- /dev/null +++ b/src/app/api/division/[id]/detail/route.ts @@ -0,0 +1,157 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import _ from "lodash"; +import moment from "moment"; +import { NextResponse } from "next/server"; + + +// GET ONE DATA DIVISI :: UNTUK TAMPIL DETAIL DIVISI (FITUR DIVISI) PADA HALAMAN DETAIL +export async function GET(request: Request, context: { params: { id: string } }) { + try { + let allData + const { id } = context.params; + const user = await funGetUserByCookies() + const { searchParams } = new URL(request.url); + const kategori = searchParams.get("cat"); + + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + + const data = await prisma.division.findUnique({ + where: { + id: String(id), + isActive: true + } + }); + + if (!data) { + return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan", }, { status: 404 }); + } + + if (kategori == "jumlah") { + const tugas = await prisma.divisionProject.count({ + where: { + idDivision: String(id), + status: { + lte: 1 + }, + isActive: true + } + }) + + const dokumen = await prisma.divisionDocumentFolderFile.count({ + where: { + idDivision: String(id), + isActive: true, + category: "FILE" + } + }) + + const diskusi = await prisma.divisionDisscussion.count({ + where: { + idDivision: String(id), + isActive: true, + status: 1 + } + }) + + const kalender = await prisma.divisionCalendar.count({ + where: { + idDivision: String(id), + isActive: true, + dateStart: { + lte: new Date() + } + } + }) + + + allData = { + tugas: tugas, + dokumen: dokumen, + diskusi: diskusi, + kalender: kalender + } + } else if (kategori == "today-task") { + const tugas = await prisma.divisionProjectTask.findMany({ + skip: 0, + take: 5, + where: { + idDivision: String(id), + status: 0, + isActive: true, + dateStart: new Date() + }, + select: { + id: true, + title: true, + dateStart: true, + dateEnd: true, + } + }) + + allData = tugas.map((v: any) => ({ + ..._.omit(v, ["dateStart", "dateEnd"]), + dateStart: moment(v.dateStart).format("LL"), + dateEnd: moment(v.dateEnd).format("LL") + })) + } else if (kategori == "new-file") { + allData = await prisma.divisionDocumentFolderFile.findMany({ + skip: 0, + take: 5, + where: { + idDivision: String(id), + isActive: true, + category: "FILE" + }, + select: { + id: true, + name: true, + extension: true, + }, + orderBy: { + createdAt: "desc" + } + }) + } else if (kategori == "new-discussion") { + const diskusi = await prisma.divisionDisscussion.findMany({ + skip: 0, + take: 5, + where: { + idDivision: String(id), + isActive: true, + status: 1 + }, + select: { + id: true, + title: true, + createdAt: true, + User: { + select: { + name: true + } + } + }, + orderBy: { + createdAt: "desc" + } + }) + + allData = diskusi.map((v: any) => ({ + ..._.omit(v, ["createdAt", "User"]), + date: moment(v.dateStart).format("LL"), + user: v.User.name + })) + } + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: allData }, { status: 200 }); + } + + + + catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/division/[id]/route.ts b/src/app/api/division/[id]/route.ts new file mode 100644 index 0000000..43f1c60 --- /dev/null +++ b/src/app/api/division/[id]/route.ts @@ -0,0 +1,32 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import { NextResponse } from "next/server"; + + +// GET ONE DATA DIVISI :: UNTUK TAMPIL DATA DI HALAMAN EDIT +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.division.findUnique({ + where: { + id: String(id), + isActive: true + } + }); + + if (!data) { + return NextResponse.json( { success: false, message: "Gagal mendapatkan divisi, data tidak ditemukan", }, { status: 404 } ); + } + + return NextResponse.json( { success: true, message: "Berhasil mendapatkan divisi", data, }, { status: 200 } ); + + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/division/route.ts b/src/app/api/division/route.ts new file mode 100644 index 0000000..a868884 --- /dev/null +++ b/src/app/api/division/route.ts @@ -0,0 +1,114 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import _ from "lodash"; +import { revalidatePath, revalidateTag } from "next/cache"; +import { NextResponse } from "next/server"; + + +// GET ALL DATA DIVISI == LIST DATA DIVISI +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 }); + } + + let grup + const villaId = user.idVillage + const { searchParams } = new URL(request.url); + const idGroup = searchParams.get("group"); + const name = searchParams.get('search'); + + if (idGroup == null || idGroup == undefined) { + grup = user.idGroup + } else { + grup = idGroup + } + + const data = await prisma.division.findMany({ + where: { + isActive: true, + idVillage: String(villaId), + idGroup: grup, + name: { + contains: (name == undefined || name == null) ? "" : name, + mode: "insensitive" + } + }, + select: { + id: true, + name: true, + desc: true, + DivisionMember: { + where: { + isActive: true + }, + select: { + idUser: true + } + } + } + }); + + const allData = data.map((v: any) => ({ + ..._.omit(v, ["DivisionMember"]), + jumlah_member: v.DivisionMember.length + })) + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan divisi", data: allData, }, { status: 200 }); + + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + + + + + +// CREATE DATA DIVISI +export async function POST(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 sent = (await request.json()); + const villaId = user.idVillage + const data = await prisma.division.create({ + data: { + name: sent.data.name, + idVillage: String(user.idVillage), + idGroup: sent.data.idGroup, + desc: sent.data.desc, + createdBy: String(user.id) + }, + select: { + id: true + } + }) + + + const dataMember = sent.member.map((v: any) => ({ + ..._.omit(v, ["idUser","name"]), + idUser: v.idUser, + idDivision: data.id, + isAdmin: sent.admin.some((i: any) => i == v.idUser) + })) + + const insertMember = await prisma.divisionMember.createMany({ + data: dataMember + }) + + revalidatePath('/api/divisi/', "page") + revalidatePath('/divisi', 'page') + revalidateTag('divisi') + + return NextResponse.json({ success: true, message: "Berhasil menambahkan divisi", data, }, { status: 200 }); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal menambahkan divisi, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +}; \ No newline at end of file diff --git a/src/module/division_new/components/detail_division/carousel_division.tsx b/src/module/division_new/components/carousel_division.tsx similarity index 100% rename from src/module/division_new/components/detail_division/carousel_division.tsx rename to src/module/division_new/components/carousel_division.tsx diff --git a/src/module/division_new/components/create_admin_division.tsx b/src/module/division_new/components/create_admin_division.tsx index 8c2569e..acc3b74 100644 --- a/src/module/division_new/components/create_admin_division.tsx +++ b/src/module/division_new/components/create_admin_division.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import NavbarAdminDivision from './ui/navbar_admin_division'; +import NavbarAdminDivision from './navbar_admin_division'; export default function CreateAdminDivision({ data }: { data: any }) { return ( diff --git a/src/module/division_new/components/create_division.tsx b/src/module/division_new/components/create_division.tsx index 865b31a..a8bec20 100644 --- a/src/module/division_new/components/create_division.tsx +++ b/src/module/division_new/components/create_division.tsx @@ -22,9 +22,9 @@ import toast from "react-hot-toast"; import { funGetUserByCookies } from "@/module/auth"; import CreateAdminDivision from "./create_admin_division"; import CreateUsers from "./create_users"; -import NavbarCreateUsers from "./ui/navbar_create_users"; -import NavbarAdminDivision from "./ui/navbar_admin_division"; import { funGetAllGroup, IDataGroup } from "@/module/group"; +import NavbarAdminDivision from "./navbar_admin_division"; +import NavbarCreateUsers from "./navbar_create_users"; export default function CreateDivision() { const router = useRouter(); @@ -88,6 +88,8 @@ export default function CreateDivision() { loadData(); }, []); + + if (isChooseAdmin) return { if (val) { member.set([]) @@ -204,7 +206,6 @@ export default function CreateDivision() { fullWidth onClick={() => { onSubmit() - // router.push("/division/create?page=pilih-admin") }} > Simpan diff --git a/src/module/division_new/components/create_users.tsx b/src/module/division_new/components/create_users.tsx index bcda7e1..11869d4 100644 --- a/src/module/division_new/components/create_users.tsx +++ b/src/module/division_new/components/create_users.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import NavbarCreateUsers from './ui/navbar_create_users'; +import NavbarCreateUsers from './navbar_create_users'; export default function CreateUsers({ grup }: { grup: string }) { return ( diff --git a/src/module/division_new/components/detail_division/detail_division.tsx b/src/module/division_new/components/detail_division/detail_division.tsx deleted file mode 100644 index ab2585d..0000000 --- a/src/module/division_new/components/detail_division/detail_division.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { ActionIcon, Box, Stack } from '@mantine/core'; -import React from 'react'; -import CarouselDivision from './carousel_division'; -import FeatureDetailDivision from './feature_detail_division'; -import ListDiscussionOnDetailDivision from './list_discussion'; -import ListTaskOnDetailDivision from './list_task'; -import ListDocumentOnDetailDivision from './list_document'; -import NavbarDetailDivision from '../ui/navbar_detail_division'; - -export default function DetailDivision() { - return ( - <> - // - // - // - // - // - // - // - // - // - // - // - // - ); -} - diff --git a/src/module/division_new/components/detail_division/list_document.tsx b/src/module/division_new/components/detail_division/list_document.tsx deleted file mode 100644 index 4498727..0000000 --- a/src/module/division_new/components/detail_division/list_document.tsx +++ /dev/null @@ -1,69 +0,0 @@ -'use client' -import { WARNA } from "@/module/_global"; -import { Carousel } from "@mantine/carousel"; -import { Box, Image, Text, Center, Paper, Stack, UnstyledButton } from "@mantine/core"; -import * as ICON from '../../../division/lib/file_icon' -import { useRouter } from "next/navigation"; - -const iconContainer = (icon: string) => 'data:image/svg+xml;base64,' + btoa(icon) - -const listDocument = [ - - { - "id": "1", - "title": "image 1", - "description": "description 1", - "image": iconContainer(ICON.IMAGE), - }, - { - "id": "2", - "title": "data pdf", - "description": "description 2", - "image": iconContainer(ICON.PDF), - }, - { - "id": "3", - "title": "data pdf 3", - "description": "description 3", - "image": iconContainer(ICON.PDF), - }, - { - "id": "4", - "title": "text 4", - "description": "description 4", - "image": iconContainer(ICON.TEXT), - }, - { - "id": "5", - "title": "text 5", - "description": "description 5", - "image": iconContainer(ICON.TEXT), - } -] - -export default function ListDocumentOnDetailDivision() { - const router = useRouter() - return ( - - Dokumen Terbaru - - { - listDocument.map((v) => - router.push(`/document`)}> - - -
- image -
-
- - {v.title} - -
-
-
- )} -
-
- ) -} \ No newline at end of file diff --git a/src/module/division_new/components/detail_division/list_task.tsx b/src/module/division_new/components/detail_division/list_task.tsx deleted file mode 100644 index c8e8cfd..0000000 --- a/src/module/division_new/components/detail_division/list_task.tsx +++ /dev/null @@ -1,66 +0,0 @@ -'use client' -import { WARNA } from "@/module/_global"; -import { Carousel } from "@mantine/carousel"; -import { Avatar, Box, Group, Text } from "@mantine/core"; -import { useRouter } from "next/navigation"; -import { CiClock2 } from "react-icons/ci"; -import { MdAccountCircle } from "react-icons/md"; - -const dataTask = [ - { - id: 1, - title: 'Melakukan Tugas Mengenai Darmasaba', - date: '21 Juni 2024', - jumlah: 5 - }, - { - id: 2, - title: 'Pembuatan Laporan Kegiatan', - date: '21 Juni 2024', - jumlah: 3 - }, - { - id: 3, - title: 'Meeting Pembahasan Proposal', - date: '21 Juni 2024', - jumlah: 8 - }, - { - id: 4, - title: 'Laporan Anggaran Tahunan', - date: '21 Juni 2024', - jumlah: 4 - } -] - -export default function ListTaskOnDetailDivision() { - const router = useRouter() - return ( - - Tugas Hari Ini - - {dataTask.map((v, i) => - - router.push(`/task/${v.id}`)} bg={WARNA.biruTua} style={{ borderRadius: 10, border: `1px solid ${"#D6D8F6"}` }}> - {v.title} - - - - {v.date} - - - - - - - +{v.jumlah} - - - - - - )} - - - ) -} \ No newline at end of file diff --git a/src/module/division_new/components/ui/drawer_detail_division.tsx b/src/module/division_new/components/drawer_detail_division.tsx similarity index 100% rename from src/module/division_new/components/ui/drawer_detail_division.tsx rename to src/module/division_new/components/drawer_detail_division.tsx diff --git a/src/module/division_new/components/ui/drawer_division.tsx b/src/module/division_new/components/drawer_division.tsx similarity index 100% rename from src/module/division_new/components/ui/drawer_division.tsx rename to src/module/division_new/components/drawer_division.tsx diff --git a/src/module/division_new/components/detail_division/feature_detail_division.tsx b/src/module/division_new/components/feature_detail_division.tsx similarity index 75% rename from src/module/division_new/components/detail_division/feature_detail_division.tsx rename to src/module/division_new/components/feature_detail_division.tsx index c5e2237..662dfae 100644 --- a/src/module/division_new/components/detail_division/feature_detail_division.tsx +++ b/src/module/division_new/components/feature_detail_division.tsx @@ -1,7 +1,7 @@ "use client" import { WARNA } from '@/module/_global'; import { ActionIcon, Box, Center, Grid, Group, SimpleGrid, Text } from '@mantine/core'; -import React from 'react'; +import React, { useState } from 'react'; import { HiMiniUserGroup } from 'react-icons/hi2'; import { IoIosArrowRoundForward } from 'react-icons/io'; import { LuClipboardEdit } from "react-icons/lu"; @@ -9,10 +9,36 @@ import { GoCommentDiscussion } from "react-icons/go"; import { BsFileEarmarkText } from "react-icons/bs"; import { IoCalendarOutline } from "react-icons/io5"; import { LuFileSignature } from "react-icons/lu"; -import { useRouter } from 'next/navigation'; +import { useParams, useRouter } from 'next/navigation'; +import { funGetDetailDivisionById } from '../lib/api_division'; +import toast from 'react-hot-toast'; +import { useShallowEffect } from '@mantine/hooks'; +import { IDataJumlahDetailDivision } from '../lib/type_division'; -export default function FeatureDetailDivision({ id }: { id: string }) { +export default function FeatureDetailDivision() { + const param = useParams<{ id: string }>() const router = useRouter() + const [feature, setFeature] = useState() + + async function fetchData() { + try { + const res = await funGetDetailDivisionById(param.id, 'jumlah'); + if (res.success) { + setFeature(res.data) + } else { + toast.error(res.message); + } + } catch (error) { + console.error(error); + toast.error("Gagal mendapatkan divisi, coba lagi nanti"); + } + } + + useShallowEffect(() => { + fetchData() + }, [param.id]) + + return ( Features @@ -27,7 +53,7 @@ export default function FeatureDetailDivision({ id }: { id: string }) { border: `1px solid ${WARNA.bgHijauMuda}`, borderRadius: 10, padding: 10 - }} onClick={() => router.push(id + '/task')}> + }} onClick={() => router.push(param.id + '/task')}> Tugas - 23 Tugas + {feature?.tugas} Tugas @@ -52,7 +78,7 @@ export default function FeatureDetailDivision({ id }: { id: string }) { border: `1px solid ${WARNA.bgHijauMuda}`, borderRadius: 10, padding: 10 - }} onClick={() => router.push(id + '/document')}> + }} onClick={() => router.push(param.id + '/document')}> Dokumen - 23 Tugas + {feature?.dokumen} File @@ -77,7 +103,7 @@ export default function FeatureDetailDivision({ id }: { id: string }) { border: `1px solid ${WARNA.bgHijauMuda}`, borderRadius: 10, padding: 10 - }} onClick={() => router.push(id + '/discussion')}> + }} onClick={() => router.push(param.id + '/discussion')}> Diskusi - 23 Tugas + {feature?.diskusi} Diskusi @@ -102,7 +128,7 @@ export default function FeatureDetailDivision({ id }: { id: string }) { border: `1px solid ${WARNA.bgHijauMuda}`, borderRadius: 10, padding: 10 - }} onClick={() => router.push(id + '/calender')}> + }} onClick={() => router.push(param.id + '/calender')}> Kalender - 23 Tugas + {feature?.kalender} Acara diff --git a/src/module/division_new/components/detail_division/list_discussion.tsx b/src/module/division_new/components/list_discussion.tsx similarity index 53% rename from src/module/division_new/components/detail_division/list_discussion.tsx rename to src/module/division_new/components/list_discussion.tsx index 2f8926b..53fca79 100644 --- a/src/module/division_new/components/detail_division/list_discussion.tsx +++ b/src/module/division_new/components/list_discussion.tsx @@ -1,9 +1,14 @@ "use client" import { WARNA } from "@/module/_global"; -import { Box, Group, Text } from "@mantine/core"; -import { useRouter } from "next/navigation"; +import { Box, Group, Skeleton, Stack, Text } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { useParams, useRouter } from "next/navigation"; +import { useState } from "react"; +import toast from "react-hot-toast"; import { CiUser, CiClock2 } from "react-icons/ci"; import { GoDiscussionClosed } from "react-icons/go"; +import { funGetDetailDivisionById } from "../lib/api_division"; +import { IDataDiscussionOnDetailDivision } from "../lib/type_division"; const dataDiskusi = [ { @@ -34,6 +39,32 @@ const dataDiskusi = [ export default function ListDiscussionOnDetailDivision() { const router = useRouter(); + const param = useParams<{ id: string }>() + const [data, setData] = useState([]) + const [loading, setLoading] = useState(true); + + async function fetchData() { + try { + setLoading(true); + const res = await funGetDetailDivisionById(param.id, 'new-discussion'); + if (res.success) { + setData(res.data) + } else { + toast.error(res.message); + } + setLoading(false); + } catch (error) { + console.error(error); + toast.error("Gagal mendapatkan divisi, coba lagi nanti"); + } finally { + setLoading(false); + } + } + + useShallowEffect(() => { + fetchData() + }, [param.id]) + return ( <> @@ -48,7 +79,28 @@ export default function ListDiscussionOnDetailDivision() { padding: 20, }} > - {dataDiskusi.map((v, i) => { + + { + loading ? + Array(2) + .fill(null) + .map((_, i) => ( + + + + + + + + )) + : + (data.length === 0) ? + + Belum ada diskusi + + : <> + } + {data.map((v, i) => { return ( - {v.judul} + {v.title} diff --git a/src/module/division_new/components/ui/navbar_division.tsx b/src/module/division_new/components/list_division.tsx similarity index 82% rename from src/module/division_new/components/ui/navbar_division.tsx rename to src/module/division_new/components/list_division.tsx index e9a50a6..e53e22b 100644 --- a/src/module/division_new/components/ui/navbar_division.tsx +++ b/src/module/division_new/components/list_division.tsx @@ -8,37 +8,50 @@ import { HiMagnifyingGlass, HiMiniPresentationChartBar, HiMiniUserGroup, HiOutli import { MdAccountCircle } from 'react-icons/md'; import DrawerDivision from './drawer_division'; import { useShallowEffect } from '@mantine/hooks'; +import { IDataDivison } from '../lib/type_division'; +import { funGetAllDivision } from '../lib/api_division'; +import toast from 'react-hot-toast'; -type TypeDivision = { - id: string - name: string - idGroup: string - idVillage: string - desc: string - isActive: boolean -}[] - -export default function NavbarDivision() { +export default function ListDivision() { const [isList, setIsList] = useState(false) const router = useRouter() const [openDrawer, setOpenDrawer] = useState(false) - const [data, setData] = useState() + const [data, setData] = useState([]) const [jumlah, setJumlah] = useState(0) + const [searchQuery, setSearchQuery] = useState('') const handleList = () => { setIsList(!isList) } - async function loadData() { - const response = await fetch(API_ADDRESS.apiGetAllDivision) - const data = await response.json() - setData(data) - setJumlah(data.length) + const fetchData = async (search: string) => { + try { + setData([]); + const response = await funGetAllDivision('?search=' + search) + + if (response.success) { + setData(response.data) + setJumlah(response.data.length) + } else { + toast.error(response.message); + } + + } catch (error) { + toast.error("Gagal mendapatkan divisi, coba lagi nanti"); + console.error(error); + } + }; + + function searchDivision(search: string) { + setSearchQuery(search) + fetchData(search) } useShallowEffect(() => { - loadData() - }, []) + fetchData(searchQuery) + }, [searchQuery]) + + return ( @@ -61,6 +74,8 @@ export default function NavbarDivision() { radius={30} leftSection={} placeholder="Pencarian" + value={searchQuery} + onChange={(val) => { searchDivision(val.target.value) }} /> @@ -131,7 +146,7 @@ export default function NavbarDivision() { - +5 + +{v.jumlah_member - 1} diff --git a/src/module/division_new/components/list_document.tsx b/src/module/division_new/components/list_document.tsx new file mode 100644 index 0000000..b8889be --- /dev/null +++ b/src/module/division_new/components/list_document.tsx @@ -0,0 +1,86 @@ +'use client' +import { WARNA } from "@/module/_global"; +import { Carousel } from "@mantine/carousel"; +import { Box, Image, Text, Center, Paper, Stack, UnstyledButton, Skeleton, Group } from "@mantine/core"; +import * as ICON from '../../division/lib/file_icon' +import { useParams, useRouter } from "next/navigation"; +import { useShallowEffect } from "@mantine/hooks"; +import toast from "react-hot-toast"; +import { funGetDetailDivisionById } from "../lib/api_division"; +import { IDataKalenderOnDetailDivision } from "../lib/type_division"; +import { useState } from "react"; + +const iconContainer = (icon: string) => 'data:image/svg+xml;base64,' + btoa(icon) + +export default function ListDocumentOnDetailDivision() { + const router = useRouter() + const param = useParams<{ id: string }>() + const [data, setData] = useState([]) + const [loading, setLoading] = useState(true); + + async function fetchData() { + try { + setLoading(true); + const res = await funGetDetailDivisionById(param.id, 'new-file'); + if (res.success) { + setData(res.data) + } else { + toast.error(res.message); + } + setLoading(false); + } catch (error) { + console.error(error); + toast.error("Gagal mendapatkan divisi, coba lagi nanti"); + } finally { + setLoading(false); + } + } + + useShallowEffect(() => { + fetchData() + }, [param.id]) + + return ( + + Dokumen Terbaru + + { + loading + ? + Array(4) + .fill(null) + .map((_, i) => ( + + + + + )) + : (data.length === 0) ? + + Belum ada file + + : <> + } + + + { + data.map((v) => + + router.push(`/document`)}> + + +
+ image +
+
+ + {v.name + '.' + v.extension} + +
+
+
+ )} +
+
+ ) +} \ No newline at end of file diff --git a/src/module/division_new/components/list_task.tsx b/src/module/division_new/components/list_task.tsx new file mode 100644 index 0000000..b85e699 --- /dev/null +++ b/src/module/division_new/components/list_task.tsx @@ -0,0 +1,89 @@ +'use client' +import { WARNA } from "@/module/_global"; +import { Carousel } from "@mantine/carousel"; +import { Avatar, Box, Group, Skeleton, Stack, Text } from "@mantine/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { useParams, useRouter } from "next/navigation"; +import toast from "react-hot-toast"; +import { CiClock2 } from "react-icons/ci"; +import { funGetDetailDivisionById } from "../lib/api_division"; +import { useState } from "react"; +import { IDataTaskOnDetailDivision } from "../lib/type_division"; + + +export default function ListTaskOnDetailDivision() { + const router = useRouter() + const param = useParams<{ id: string }>() + const [data, setData] = useState([]) + const [loading, setLoading] = useState(true); + + async function fetchData() { + try { + setLoading(true); + const res = await funGetDetailDivisionById(param.id, 'today-task'); + if (res.success) { + setData(res.data) + } else { + toast.error(res.message); + } + setLoading(false); + } catch (error) { + console.error(error); + toast.error("Gagal mendapatkan divisi, coba lagi nanti"); + } finally { + setLoading(false); + } + } + + useShallowEffect(() => { + fetchData() + }, [param.id]) + + return ( + + Tugas Hari Ini + + { + loading ? + Array(2) + .fill(null) + .map((_, i) => ( + + + + + )) + : + (data.length === 0) ? + + Belum ada tugas hari ini + + : <> + } + + + {data.map((v, i) => + + router.push(`/task/${v.id}`)} bg={WARNA.biruTua} style={{ borderRadius: 10, border: `1px solid ${"#D6D8F6"}` }}> + {v.title} + + + + {v.dateStart} + + + {/* + + + + +{v.jumlah} + */} + + + + + )} + + + ) +} \ No newline at end of file diff --git a/src/module/division_new/components/ui/navbar_admin_division.tsx b/src/module/division_new/components/navbar_admin_division.tsx similarity index 67% rename from src/module/division_new/components/ui/navbar_admin_division.tsx rename to src/module/division_new/components/navbar_admin_division.tsx index f5f7853..dcd506b 100644 --- a/src/module/division_new/components/ui/navbar_admin_division.tsx +++ b/src/module/division_new/components/navbar_admin_division.tsx @@ -5,12 +5,15 @@ import { Avatar, Box, Button, Checkbox, Divider, Flex, Group, Stack, Text, TextI import { useRouter } from 'next/navigation'; import React, { useState } from 'react'; import { HiMagnifyingGlass } from 'react-icons/hi2'; -import { globalMemberDivision } from '../../lib/val_division'; import toast from 'react-hot-toast'; +import { globalMemberDivision } from '../lib/val_division'; +import { funCreateDivision } from '../lib/api_division'; +import { IFormMemberDivision } from '../lib/type_division'; export default function NavbarAdminDivision({ data, onSuccess }: { data: any, onSuccess: (val: any) => void }) { const router = useRouter() const member = useHookstate(globalMemberDivision) + const memberValue = member.get() as IFormMemberDivision[] const [value, setValue] = useState([]); async function onSubmit() { @@ -19,31 +22,50 @@ export default function NavbarAdminDivision({ data, onSuccess }: { data: any, on } try { - const res = await fetch(API_ADDRESS.apiCreateDivision, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - data: data, - member: member.get(), - admin: value - }) - }) + const response = await funCreateDivision({ data: data, member: memberValue, admin: value }) - const errorData = await res.json(); - - if (res.status == 201) { - toast.success('Sukses! data tersimpan') + if (response.success) { + toast.success(response.message); onSuccess(true) } else { - toast.error(errorData.message); + toast.error(response.message) onSuccess(false) } + } catch (error) { - toast.error('Error') + console.log(error); onSuccess(false) + toast.error("Gagal menambahkan grup, coba lagi nanti"); } + + + + // try { + // const res = await fetch(API_ADDRESS.apiCreateDivision, { + // method: 'POST', + // headers: { + // 'Content-Type': 'application/json' + // }, + // body: JSON.stringify({ + // data: data, + // member: member.get(), + // admin: value + // }) + // }) + + // const errorData = await res.json(); + + // if (res.status == 201) { + // toast.success('Sukses! data tersimpan') + // onSuccess(true) + // } else { + // toast.error(errorData.message); + // onSuccess(false) + // } + // } catch (error) { + // toast.error('Error') + // onSuccess(false) + // } } return ( @@ -83,7 +105,7 @@ export default function NavbarAdminDivision({ data, onSuccess }: { data: any, on
- +
diff --git a/src/module/division_new/components/ui/navbar_create_users.tsx b/src/module/division_new/components/navbar_create_users.tsx similarity index 83% rename from src/module/division_new/components/ui/navbar_create_users.tsx rename to src/module/division_new/components/navbar_create_users.tsx index 779efc5..4eea828 100644 --- a/src/module/division_new/components/ui/navbar_create_users.tsx +++ b/src/module/division_new/components/navbar_create_users.tsx @@ -6,43 +6,10 @@ import { useShallowEffect } from '@mantine/hooks'; import { useRouter } from 'next/navigation'; import React, { useState } from 'react'; import { HiMagnifyingGlass } from 'react-icons/hi2'; -import { globalMemberDivision } from '../../lib/val_division'; import { TypeUser } from '@/module/user'; import { funGetUserByCookies } from '@/module/auth'; import toast from 'react-hot-toast'; - -const dataUser = [ - { - id: 1, - img: "https://i.pravatar.cc/1000?img=3", - name: "Doni Setiawan", - }, - { - id: 2, - img: "https://i.pravatar.cc/1000?img=10", - name: "Ilham Udin", - }, - { - id: 3, - img: "https://i.pravatar.cc/1000?img=11", - name: "Didin Anang", - }, - { - id: 4, - img: "https://i.pravatar.cc/1000?img=21", - name: "Angga Saputra", - }, - { - id: 5, - img: "https://i.pravatar.cc/1000?img=32", - name: "Marcel Widianto", - }, - { - id: 6, - img: "https://i.pravatar.cc/1000?img=37", - name: "Bagas Nusantara", - }, -]; +import { globalMemberDivision } from '../lib/val_division'; export default function NavbarCreateUsers({ grup, onClose }: { grup?: string, onClose: (val: any) => void }) { @@ -55,7 +22,7 @@ export default function NavbarCreateUsers({ grup, onClose }: { grup?: string, on if (selectedFiles.some((i: any) => i.id == dataMember[index].id)) { setSelectedFiles(selectedFiles.filter((i: any) => i.id != dataMember[index].id)) } else { - setSelectedFiles([...selectedFiles, dataMember[index]]) + setSelectedFiles([...selectedFiles, {idUser: dataMember[index].id, name: dataMember[index].name}]) } }; @@ -110,7 +77,7 @@ export default function NavbarCreateUsers({ grup, onClose }: { grup?: string, on verticalSpacing={{ base: "md", sm: "xl" }} > {dataMember.map((v, index) => { - const isSelected = selectedFiles.some((i: any) => i.id == dataMember[index].id); + const isSelected = selectedFiles.some((i: any) => i.idUser == dataMember[index].id); return ( () + const [name, setName] = useState('') + + async function getOneData() { + try { + const res = await funGetDivisionById(param.id); + if (res.success) { + setName(res.data.name); + } else { + toast.error(res.message); + } + + } catch (error) { + console.error(error); + toast.error("Gagal mendapatkan grup, coba lagi nanti"); + } + } + + useShallowEffect(() => { + getOneData(); + }, [param.id]) + + return ( + <> + (setOpenDrawer(true))} bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings"> + + + } /> + setOpenDrawer(false)}> + + + + + + ); +} \ No newline at end of file diff --git a/src/module/division_new/components/ui/navbar_detail_division.tsx b/src/module/division_new/components/ui/navbar_detail_division.tsx deleted file mode 100644 index 7a13db7..0000000 --- a/src/module/division_new/components/ui/navbar_detail_division.tsx +++ /dev/null @@ -1,24 +0,0 @@ -'use client' -import { LayoutDrawer, LayoutNavbarNew, WARNA } from "@/module/_global"; -import { ActionIcon, Box } from "@mantine/core"; -import { useState } from "react"; -import { HiMenu } from "react-icons/hi"; -import DrawerDetailDivision from "./drawer_detail_division"; - -export default function NavbarDetailDivision({ title }: { title: string }) { - const [openDrawer, setOpenDrawer] = useState(false) - return ( - <> - (setOpenDrawer(true))} bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings"> - - - } /> - setOpenDrawer(false)}> - - - - - - ); -} \ No newline at end of file diff --git a/src/module/division_new/index.ts b/src/module/division_new/index.ts index a376863..3fad27e 100644 --- a/src/module/division_new/index.ts +++ b/src/module/division_new/index.ts @@ -1,3 +1,4 @@ +import { IFormDivision, IFormMemberDivision, IFormFixDivision, IDataDivison } from './lib/type_division'; import CreateUserDivisionCalender from "./_division_fitur/calender/components/create_user_division_calender"; import UlangiEvent from "./_division_fitur/calender/components/ulangi_event"; import UpdateUlangiEvent from "./_division_fitur/calender/components/update_calander/update_ulangi_event"; @@ -21,20 +22,22 @@ import { apiDivision } from "./api/api_division"; import CreateAdminDivision from "./components/create_admin_division"; import CreateUsers from "./components/create_users"; import ViewCreateAnggotaDivision from "./view/view_create_anggota_division"; -import ViewCreateDivision from "./view/view_create_division"; import ViewCreateReport from "./view/view_create_report"; -import ViewDetailDivision from "./view/view_detail_division"; -import ViewDivision from "./view/view_division"; import ViewEditDivision from "./view/view_edit_division"; import ViewInformationDivision from "./view/view_Information_division"; import ViewReportDivision from "./view/view_report_division"; +import ListDivision from './components/list_division'; +import CreateDivision from './components/create_division'; +import NavbarDetailDivision from './components/navbar_detail_division'; +import CarouselDivision from './components/carousel_division'; +import FeatureDetailDivision from './components/feature_detail_division'; +import ListTaskOnDetailDivision from './components/list_task'; +import ListDocumentOnDetailDivision from './components/list_document'; +import ListDiscussionOnDetailDivision from './components/list_discussion'; -export { ViewDivision }; -export { ViewCreateDivision }; export { CreateUsers }; export { CreateAdminDivision }; export { ViewCreateReport }; -export { ViewDetailDivision }; export { ViewDivisionTask }; export { ViewDetailDivisionTask }; export { ViewUpdateProgressDivisionTask }; @@ -59,3 +62,12 @@ export { ViewEditDivision }; export { ViewCreateAnggotaDivision }; export { apiDivision } export { apiDiscussion } +export type { IFormDivision, IFormMemberDivision, IFormFixDivision, IDataDivison } +export { ListDivision } +export { CreateDivision } +export { NavbarDetailDivision } +export { CarouselDivision } +export { FeatureDetailDivision } +export { ListTaskOnDetailDivision } +export { ListDocumentOnDetailDivision } +export { ListDiscussionOnDetailDivision } diff --git a/src/module/division_new/lib/api_division.ts b/src/module/division_new/lib/api_division.ts new file mode 100644 index 0000000..5a376d7 --- /dev/null +++ b/src/module/division_new/lib/api_division.ts @@ -0,0 +1,27 @@ +import { IFormFixDivision } from "./type_division"; + +export const funGetAllDivision = async (path?: string) => { + const response = await fetch(`/api/division${(path) ? path : ''}`, { next: { tags: ['division'] } }); + return await response.json().catch(() => null); +} + +export const funGetDivisionById = async (path: string) => { + const response = await fetch(`/api/division/${path}`); + return await response.json().catch(() => null); +} + +export const funGetDetailDivisionById = async (path: string, kategori: string) => { + const response = await fetch(`/api/division/${path}/detail?cat=${kategori}`); + return await response.json().catch(() => null); +} + +export const funCreateDivision = async (data: IFormFixDivision) => { + const response = await fetch("/api/division", { + 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/division_new/lib/type_division.ts b/src/module/division_new/lib/type_division.ts new file mode 100644 index 0000000..4c7f5cc --- /dev/null +++ b/src/module/division_new/lib/type_division.ts @@ -0,0 +1,50 @@ +export interface IFormDivision { + name: string + idGroup: string + desc: string +} + +export interface IFormMemberDivision { + idUser: string, + name: string +} + +export interface IFormFixDivision { + data: IFormDivision, + member: IFormMemberDivision[], + admin: string[] +} + +export interface IDataDivison { + id: string, + name: string, + desc: string, + jumlah_member: number +} + +export interface IDataJumlahDetailDivision { + tugas: number, + dokumen: number, + diskusi: number, + kalender: number +} + +export interface IDataTaskOnDetailDivision { + id: string, + title: string, + dateStart: string, + dateEnd: string +} + +export interface IDataKalenderOnDetailDivision { + id: string, + name: string, + extension: string, +} + +export interface IDataDiscussionOnDetailDivision { + id: string, + title: string, + date: string, + user: string +} \ No newline at end of file diff --git a/src/module/division_new/lib/val_division.ts b/src/module/division_new/lib/val_division.ts index b6085d9..2d769e0 100644 --- a/src/module/division_new/lib/val_division.ts +++ b/src/module/division_new/lib/val_division.ts @@ -1,4 +1,4 @@ -import { TypeUser } from "@/module/user"; import { hookstate } from "@hookstate/core"; +import { IFormMemberDivision } from "./type_division"; -export const globalMemberDivision = hookstate([]); \ No newline at end of file +export const globalMemberDivision = hookstate([]); \ No newline at end of file diff --git a/src/module/division_new/view/view_create_division.tsx b/src/module/division_new/view/view_create_division.tsx deleted file mode 100644 index 21db4cc..0000000 --- a/src/module/division_new/view/view_create_division.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import CreateDivision from '../components/create_division'; - -export default function ViewCreateDivision() { - return ( - - ); -} diff --git a/src/module/division_new/view/view_detail_division.tsx b/src/module/division_new/view/view_detail_division.tsx deleted file mode 100644 index 5b8e3cf..0000000 --- a/src/module/division_new/view/view_detail_division.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { useEffect } from 'react'; -import DetailDivision from '../components/detail_division/detail_division'; -import { Box, Stack } from '@mantine/core'; -import CarouselDivision from '../components/detail_division/carousel_division'; -import FeatureDetailDivision from '../components/detail_division/feature_detail_division'; -import ListDiscussionOnDetailDivision from '../components/detail_division/list_discussion'; -import ListDocumentOnDetailDivision from '../components/detail_division/list_document'; -import ListTaskOnDetailDivision from '../components/detail_division/list_task'; -import NavbarDetailDivision from '../components/ui/navbar_detail_division'; -import { API_ADDRESS } from '@/module/_global'; - -export default async function ViewDetailDivision({ id }: { id: string }) { - - const res = await fetch(`${process.env.URL + API_ADDRESS.apiGetOneDetailDivision}&divisionId=${id}`); - const data = await res.json(); - - console.log(data) - - return ( - // - - - - - - - - - - - - - ); -} - diff --git a/src/module/division_new/view/view_division.tsx b/src/module/division_new/view/view_division.tsx deleted file mode 100644 index c35d03c..0000000 --- a/src/module/division_new/view/view_division.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import NavbarDivision from '../components/ui/navbar_division'; - -export default function ViewDivision() { - return ( - - ); -} - diff --git a/src/module/group/ui/edit_drawer_group.tsx b/src/module/group/ui/edit_drawer_group.tsx index a0cd013..02d77b5 100644 --- a/src/module/group/ui/edit_drawer_group.tsx +++ b/src/module/group/ui/edit_drawer_group.tsx @@ -28,7 +28,6 @@ export default function EditDrawerGroup({ onUpdated, id, isActive, }: { onUpdate async function getOneGroup() { try { const res = await funGetGroupById(id); - console.log("amalia", res) if (res.success) { setName(res.data.name); } else {