From 4687b7382d037ede0ed66985aab97e49dc9d3d87 Mon Sep 17 00:00:00 2001 From: amel Date: Wed, 7 Aug 2024 17:39:21 +0800 Subject: [PATCH] upd: new group Deskripsi: - pembaruan api group NO Issues --- src/app/(application)/group/page.tsx | 8 +- src/app/api/group/[id]/route.ts | 138 ++++++++++++++++++ src/app/api/group/route.ts | 71 +++++++++ .../components/create_division.tsx | 5 +- src/module/group/index.ts | 12 +- src/module/group/lib/api_group.ts | 48 ++++++ src/module/group/lib/type_group.ts | 10 +- .../{components => }/ui/drawer_group.tsx | 35 ++--- .../{components => }/ui/edit_drawer_group.tsx | 0 .../{components => ui}/list_group_active.tsx | 40 +++-- .../{components => }/ui/navbar_group.tsx | 6 +- .../{components => ui}/tab_list_group.tsx | 1 - src/module/group/view/view_group.tsx | 15 -- 13 files changed, 318 insertions(+), 71 deletions(-) create mode 100644 src/app/api/group/[id]/route.ts create mode 100644 src/app/api/group/route.ts create mode 100644 src/module/group/lib/api_group.ts rename src/module/group/{components => }/ui/drawer_group.tsx (75%) rename src/module/group/{components => }/ui/edit_drawer_group.tsx (100%) rename src/module/group/{components => ui}/list_group_active.tsx (84%) rename src/module/group/{components => }/ui/navbar_group.tsx (82%) rename src/module/group/{components => ui}/tab_list_group.tsx (96%) delete mode 100644 src/module/group/view/view_group.tsx diff --git a/src/app/(application)/group/page.tsx b/src/app/(application)/group/page.tsx index ec46c75..b1232ed 100644 --- a/src/app/(application)/group/page.tsx +++ b/src/app/(application)/group/page.tsx @@ -1,9 +1,13 @@ -import { ViewGroup } from '@/module/group'; +import { NavbarGroup, TabListGroup } from '@/module/group'; +import { Box } from '@mantine/core'; import React from 'react'; function Page() { return ( - + + + + ); } diff --git a/src/app/api/group/[id]/route.ts b/src/app/api/group/[id]/route.ts new file mode 100644 index 0000000..d69123f --- /dev/null +++ b/src/app/api/group/[id]/route.ts @@ -0,0 +1,138 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import { NextResponse } from "next/server"; + +export const dynamic = 'force-dynamic' +export const revalidate = true +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.group.findUnique({ + where: { + id: id, + }, + }); + + if (!data) { + return NextResponse.json( + { + success: false, + message: "Gagal mendapatkan grup, data tidak ditemukan", + }, + { status: 404 } + ); + } + + return NextResponse.json( + { + success: true, + message: "Berhasil mendapatkan grup", + data, + }, + { status: 200 } + ); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + +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 { isActive } = (await request.json()); + const data = await prisma.group.count({ + where: { + id: id, + }, + }); + + if (data == 0) { + return NextResponse.json( + { + success: false, + message: "Edit grup gagal, data tidak ditemukan", + }, + { status: 404 } + ); + } + + const update = await prisma.group.update({ + where: { + id: id, + }, + data: { + isActive: !isActive, + }, + }); + + return NextResponse.json( + { + success: true, + message: "Grup berhasil diedit", + data, + }, + { status: 200 } + ); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + +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.group.count({ + where: { + id: id, + }, + }); + + if (data == 0) { + return NextResponse.json( + { + success: false, + message: "Edit grup gagal, data tidak ditemukan", + }, + { status: 404 } + ); + } + + const update = await prisma.group.update({ + where: { + id: id, + }, + data: { + name: name, + }, + }); + + return NextResponse.json( + { + success: true, + message: "Grup berhasil diedit", + data, + }, + { status: 200 } + ); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/group/route.ts b/src/app/api/group/route.ts new file mode 100644 index 0000000..d6df824 --- /dev/null +++ b/src/app/api/group/route.ts @@ -0,0 +1,71 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import { revalidatePath, revalidateTag } from "next/cache"; +import { NextResponse } from "next/server"; + +export const dynamic = 'force-dynamic' +export const revalidate = true +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 villaId = user.idVillage + const { searchParams } = new URL(request.url); + const isActive = searchParams.get("active"); + const name = searchParams.get('search'); + + const data = await prisma.group.findMany({ + where: { + isActive: isActive == 'false' ? false : true, + idVillage: String(villaId), + name: { + contains: (name == undefined || name == null) ? "" : name, + mode: "insensitive" + } + }, + select: { + id: true, + name: true, + isActive: true + } + }); + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan grup", data, }, { status: 200 }); + + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + + +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 { name } = (await request.json()); + const villaId = user.idVillage + const data = await prisma.group.create({ + data: { + name, + idVillage: String(villaId) + }, + }); + + revalidatePath('/api/group?active=true', "page") + revalidatePath('/api/group?active=false', 'page') + revalidatePath('/group?active=true', 'page') + revalidateTag('group') + + return NextResponse.json({ success: true, message: "Berhasil menambahkan grup", data, }, { status: 200 }); + } catch (error) { + console.log(error); + return NextResponse.json({ success: false, message: "Gagal menambahkan grup, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +}; \ No newline at end of file diff --git a/src/module/division_new/components/create_division.tsx b/src/module/division_new/components/create_division.tsx index 28e3322..2d89705 100644 --- a/src/module/division_new/components/create_division.tsx +++ b/src/module/division_new/components/create_division.tsx @@ -1,6 +1,5 @@ "use client"; import { API_ADDRESS, LayoutNavbarNew, WARNA } from "@/module/_global"; -import { TypeGroup } from "@/module/group"; import { useHookstate } from "@hookstate/core"; import { Avatar, @@ -25,11 +24,11 @@ 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 { IDataGroup } from "@/module/group"; export default function CreateDivision() { const router = useRouter(); - const [dataGroup, setDataGroup] = useState(); + const [dataGroup, setDataGroup] = useState([]); const [roleUser, setRoleUser] = useState("") const [isChooseAnggota, setChooseAnggota] = useState(false) const [isChooseAdmin, setChooseAdmin] = useState(false) diff --git a/src/module/group/index.ts b/src/module/group/index.ts index f181476..a2aee44 100644 --- a/src/module/group/index.ts +++ b/src/module/group/index.ts @@ -1,7 +1,11 @@ -import { TypeGroup } from './lib/type_group'; +import { IDataGroup, IFormGroup, IStatusGroup } from './lib/type_group'; import { apiGroup } from "./api/api_group"; -import ViewGroup from "./view/view_group"; +import { funCreateGroup, funEditGroup, funEditStatusGroup, funGetAllGroup, funGetGroupById } from './lib/api_group'; +import NavbarGroup from './ui/navbar_group'; +import TabListGroup from './ui/tab_list_group'; -export { ViewGroup }; export { apiGroup }; -export type { TypeGroup } +export type { IDataGroup, IFormGroup, IStatusGroup } +export { funGetAllGroup, funGetGroupById, funCreateGroup, funEditStatusGroup, funEditGroup } +export { NavbarGroup } +export { TabListGroup } diff --git a/src/module/group/lib/api_group.ts b/src/module/group/lib/api_group.ts new file mode 100644 index 0000000..9631eb3 --- /dev/null +++ b/src/module/group/lib/api_group.ts @@ -0,0 +1,48 @@ +import { IFormGroup, IStatusGroup } from "./type_group"; + +export const funGetAllGroup = async (path?: string) => { + const response = await fetch(`/api/group${(path) ? path : ''}`, { next: { tags: ['group'] } }); + return await response.json().catch(() => null); +}; + +export const funGetGroupById = async (path: string) => { + const response = await fetch(`/api/group/${path}`); + return await response.json().catch(() => null); +}; + +export const funCreateGroup = async (data: IFormGroup) => { + if (data.name.length < 3) + return { success: false, message: 'Minimal 3 karakter' } + + const response = await fetch("/api/group", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +}; + +export const funEditStatusGroup = async (path: string, data: IStatusGroup) => { + const response = await fetch(`/api/group/${path}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +}; + +export const funEditGroup = async (path: string, data: IFormGroup) => { + const response = await fetch(`/api/group/${path}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +}; + diff --git a/src/module/group/lib/type_group.ts b/src/module/group/lib/type_group.ts index 80de885..c3f9667 100644 --- a/src/module/group/lib/type_group.ts +++ b/src/module/group/lib/type_group.ts @@ -1,5 +1,13 @@ -export type TypeGroup = { +export interface IDataGroup { id: string name: string isActive: boolean }[] + +export interface IFormGroup { + name : string +} + +export interface IStatusGroup { + isActive: boolean; +} \ No newline at end of file diff --git a/src/module/group/components/ui/drawer_group.tsx b/src/module/group/ui/drawer_group.tsx similarity index 75% rename from src/module/group/components/ui/drawer_group.tsx rename to src/module/group/ui/drawer_group.tsx index 2382200..5dd2a7b 100644 --- a/src/module/group/components/ui/drawer_group.tsx +++ b/src/module/group/ui/drawer_group.tsx @@ -12,32 +12,29 @@ import { } from "@mantine/core"; import React, { useState } from "react"; import { IoAddCircle } from "react-icons/io5"; +import { funCreateGroup } from "../lib/api_group"; +import toast from "react-hot-toast"; -export default function DrawerGroup({ - onSuccess, -}: { - onSuccess: (val: boolean) => void; -}) { +export default function DrawerGroup({ onSuccess, }: { onSuccess: (val: boolean) => void; }) { const [openDrawerGroup, setOpenDrawerGroup] = useState(false); const [namaGroup, setNamaGroup] = useState(""); - async function onCreate() { + async function createData() { try { - const res = await fetch(API_ADDRESS.apiCreateGroup, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - name: namaGroup, - }), - }); - setOpenDrawerGroup(false); - onSuccess(true); + const response = await funCreateGroup({ name: namaGroup }) + + if (response.success) { + toast.success(response.message); + setOpenDrawerGroup(false) + onSuccess(true) + } else { + toast.error(response.message) + } + } catch (error) { console.log(error); - onSuccess(false); + toast.error("Gagal menambahkan grup, coba lagi nanti"); } } @@ -84,7 +81,7 @@ export default function DrawerGroup({ size="lg" radius={30} fullWidth - onClick={onCreate} + onClick={createData} > Simpan diff --git a/src/module/group/components/ui/edit_drawer_group.tsx b/src/module/group/ui/edit_drawer_group.tsx similarity index 100% rename from src/module/group/components/ui/edit_drawer_group.tsx rename to src/module/group/ui/edit_drawer_group.tsx diff --git a/src/module/group/components/list_group_active.tsx b/src/module/group/ui/list_group_active.tsx similarity index 84% rename from src/module/group/components/list_group_active.tsx rename to src/module/group/ui/list_group_active.tsx index 16f4388..ed7af23 100644 --- a/src/module/group/components/list_group_active.tsx +++ b/src/module/group/ui/list_group_active.tsx @@ -10,49 +10,46 @@ import { import React, { useEffect, useState } from "react"; import { HiOutlineOfficeBuilding } from "react-icons/hi"; import { HiMagnifyingGlass } from "react-icons/hi2"; -import EditDrawerGroup from "./ui/edit_drawer_group"; +import EditDrawerGroup from "./edit_drawer_group"; import toast from "react-hot-toast"; import { useShallowEffect } from "@mantine/hooks"; +import { funGetAllGroup } from "../lib/api_group"; +import { IDataGroup } from "../lib/type_group"; -type dataGroup = { - id: string; - name: string; - isActive: boolean; -}; export default function ListGroupActive({ status }: { status: boolean }) { const [openDrawer, setOpenDrawer] = useState(false); const [valChoose, setValChoose] = useState(""); - const [isData, setData] = useState([]); + const [isData, setData] = useState([]); const [selectId, setSelectId] = useState(null); const [active, setActive] = useState(null); const [searchQuery, setSearchQuery] = useState('') const [loading, setLoading] = useState(true); - const getData = async () => { + const fetchData = async () => { try { setData([]); setLoading(true); - const res = await fetch( - `${API_ADDRESS.apiGetAllGroup}&villageId=121212&active=${status}&name=${searchQuery}` - ); - const data = await res.json(); - setData(data); + + const response = await funGetAllGroup('?active=' + status + '&search=' + searchQuery) + + if (response.success) { + setData(response?.data) + } else { + toast.error(response.message); + } + setLoading(false); } catch (error) { - if (error instanceof Error) { - console.error(error); - toast.error("Terjadi kesalahan"); - } else { - console.error("Error tidak diketahui"); - } + toast.error("Gagal mendapatkan grup, coba lagi nanti"); + console.error(error); } finally { setLoading(false); } }; useShallowEffect(() => { - getData(); + fetchData(); }, [status, searchQuery]); return ( @@ -120,6 +117,7 @@ export default function ListGroupActive({ status }: { status: boolean }) { ); })} + setOpenDrawer(false)} @@ -131,7 +129,7 @@ export default function ListGroupActive({ status }: { status: boolean }) { onUpdated={(val) => { if (val) { toast.success("Sukses! data tersimpan"); - getData(); + // fetchData(); } setOpenDrawer(false); }} diff --git a/src/module/group/components/ui/navbar_group.tsx b/src/module/group/ui/navbar_group.tsx similarity index 82% rename from src/module/group/components/ui/navbar_group.tsx rename to src/module/group/ui/navbar_group.tsx index d47f734..c710b15 100644 --- a/src/module/group/components/ui/navbar_group.tsx +++ b/src/module/group/ui/navbar_group.tsx @@ -4,7 +4,6 @@ import { ActionIcon, } from '@mantine/core'; import React, { useState } from 'react'; import { HiMenu } from "react-icons/hi"; import DrawerGroup from './drawer_group'; -import toast from 'react-hot-toast'; export default function NavbarGroup() { const [isOpen, setOpen] = useState(false) @@ -18,10 +17,7 @@ export default function NavbarGroup() { } /> setOpen(false)}> - { - setOpen(false) - toast.success('Sukses! data tersimpan') - }} /> + { setOpen(false) }} /> ); diff --git a/src/module/group/components/tab_list_group.tsx b/src/module/group/ui/tab_list_group.tsx similarity index 96% rename from src/module/group/components/tab_list_group.tsx rename to src/module/group/ui/tab_list_group.tsx index 0315881..141e03b 100644 --- a/src/module/group/components/tab_list_group.tsx +++ b/src/module/group/ui/tab_list_group.tsx @@ -39,7 +39,6 @@ export default function TabListGroup() { - {/* */} diff --git a/src/module/group/view/view_group.tsx b/src/module/group/view/view_group.tsx deleted file mode 100644 index 7546655..0000000 --- a/src/module/group/view/view_group.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import NavbarGroup from '../components/ui/navbar_group'; -import { Box } from '@mantine/core'; -import ListGroupActive from '../components/list_group_active'; -import TabListGroup from '../components/tab_list_group'; - -export default function ViewGroup() { - return ( - - - - - ); -} -