From 8b97a6f27d41e4704e73895ae64c6c84e2d8e028 Mon Sep 17 00:00:00 2001 From: lukman Date: Fri, 9 Aug 2024 17:27:34 +0800 Subject: [PATCH] feat : update member --- src/app/api/user/[id]/route.ts | 174 ++++++++++++++++++ src/app/api/user/route.ts | 125 +++++++++++++ src/module/user/member/index.ts | 8 +- src/module/user/member/lib/api_member.ts | 64 +++++++ src/module/user/member/lib/type_member.ts | 49 +++++ .../{component => ui}/create_member.tsx | 0 .../ui/drawer_detail_member.tsx | 0 .../{component => }/ui/drawer_list_member.tsx | 0 .../member/{component => ui}/edit_member.tsx | 0 .../member/{component => ui}/list_member.tsx | 2 +- .../ui/navbar_create_member.tsx | 0 .../ui/navbar_detail_member.tsx | 0 .../{component => }/ui/navbar_edit_member.tsx | 0 .../{component => }/ui/navbar_list_member.tsx | 0 .../{component => }/ui/tab_list_member.tsx | 0 .../{view => ui}/view_create_member.tsx | 6 +- .../{view => ui}/view_detail_member.tsx | 4 +- .../member/{view => ui}/view_edit_member.tsx | 6 +- .../member/{view => ui}/view_list_member.tsx | 4 +- 19 files changed, 427 insertions(+), 15 deletions(-) create mode 100644 src/app/api/user/[id]/route.ts create mode 100644 src/app/api/user/route.ts create mode 100644 src/module/user/member/lib/api_member.ts create mode 100644 src/module/user/member/lib/type_member.ts rename src/module/user/member/{component => ui}/create_member.tsx (100%) rename src/module/user/member/{component => }/ui/drawer_detail_member.tsx (100%) rename src/module/user/member/{component => }/ui/drawer_list_member.tsx (100%) rename src/module/user/member/{component => ui}/edit_member.tsx (100%) rename src/module/user/member/{component => ui}/list_member.tsx (96%) rename src/module/user/member/{component => }/ui/navbar_create_member.tsx (100%) rename src/module/user/member/{component => }/ui/navbar_detail_member.tsx (100%) rename src/module/user/member/{component => }/ui/navbar_edit_member.tsx (100%) rename src/module/user/member/{component => }/ui/navbar_list_member.tsx (100%) rename src/module/user/member/{component => }/ui/tab_list_member.tsx (100%) rename src/module/user/member/{view => ui}/view_create_member.tsx (66%) rename src/module/user/member/{view => ui}/view_detail_member.tsx (73%) rename src/module/user/member/{view => ui}/view_edit_member.tsx (64%) rename src/module/user/member/{view => ui}/view_list_member.tsx (60%) diff --git a/src/app/api/user/[id]/route.ts b/src/app/api/user/[id]/route.ts new file mode 100644 index 0000000..7bc2fbd --- /dev/null +++ b/src/app/api/user/[id]/route.ts @@ -0,0 +1,174 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import { createLogUser } from "@/module/user"; +import _ from "lodash"; +import { NextResponse } from "next/server"; + +// GET ONE MEMBER / USER +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 users = await prisma.user.findUnique({ + where: { + id: id, + }, + select: { + id: true, + nik: true, + name: true, + phone: true, + email: true, + gender: true, + idGroup: true, + isActive: true, + idPosition: true, + UserRole: { + select: { + name: true, + id: true + } + }, + Position: { + select: { + name: true, + id: true + }, + }, + Group: { + select: { + name: true, + id: true + }, + }, + }, + }); + + const { ...userData } = users; + const group = users?.Group.name + const position = users?.Position.name + const idUserRole = users?.UserRole.id + + const result = { ...userData, group, position, idUserRole }; + + const omitData = _.omit(result, ["Group", "Position", "UserRole"]) + + return NextResponse.json( + { + success: true, + message: "Berhasil mendapatkan anggota", + omitData, + }, + { status: 200 } + ); + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan member, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + + +// DELETE / ACTIVE & NON ACTIVE MEMBER / USER +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.user.count({ + where: { + id: id, + }, + }); + + if (data == 0) { + return NextResponse.json( + { + success: false, + message: "Gagal mendapatkan anggota, data tidak ditemukan", + }, + { status: 404 } + ); + } + + const result = await prisma.user.update({ + where: { + id: id, + }, + data: { + isActive: !isActive, + }, + }); + + return NextResponse.json( + { + success: true, + message: "Berhasil mendapatkan anggota", + result, + }, + { status: 200 } + ); + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan anggota, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + + +// UPDATE MEMBER +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 data = await request.json(); + const cek = await prisma.user.count({ + where: { + nik: data.nik, + email: data.email, + phone: data.phone + }, + }); + + if (cek == 0) { + const updates = await prisma.user.update({ + where: { + id: id + }, + data: { + nik: data.nik, + name: data.name, + phone: data.phone, + email: data.email, + gender: data.gender, + idGroup: data.idGroup, + idPosition: data.idPosition, + idUserRole: data.idUserRole, + }, + }); + + // create log user + const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data user', table: 'user', data: data.id }) + + return Response.json( + { success: true, message: "Sukses Update User", updates }, + { status: 200 } + ); + } else { + return Response.json({ success: false, message: "User sudah ada" }, { status: 400 }); + } + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan anggota, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/user/route.ts b/src/app/api/user/route.ts new file mode 100644 index 0000000..bbc03e5 --- /dev/null +++ b/src/app/api/user/route.ts @@ -0,0 +1,125 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import { createLogUser } from "@/module/user"; +import _ from "lodash"; +import { NextResponse } from "next/server"; + +// GET ALL MEMBER / USER +export async function GET(request: Request) { + try { + + let fixGroup + const { searchParams } = new URL(request.url); + const name = searchParams.get('search') + const idGroup = searchParams.get("group"); + const active = searchParams.get("active"); + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + if (idGroup == "null" || idGroup == undefined) { + fixGroup = user.idGroup + } else { + fixGroup = idGroup + } + + const users = await prisma.user.findMany({ + where: { + isActive: active == "true" ? true : false, + idGroup: String(fixGroup), + name: { + contains: (name == undefined || name == null) ? "" : name, + mode: "insensitive", + } + }, + select: { + id: true, + isActive: true, + nik: true, + name: true, + phone: true, + email: true, + gender: true, + Position: { + select: { + name: true, + }, + }, + Group: { + select: { + name: true, + }, + }, + }, + }); + + const allData = users.map((v: any) => ({ + ..._.omit(v, ["Group"]), + group: v.Group.name + })) + + return NextResponse.json({ success: true, message: "Berhasil member", data: allData, }, { status: 200 }); + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan member, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + + +// CREATE MEMBER / USER +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 data = await request.json(); + const village = "desa1" + + const cek = await prisma.user.count({ + where: { + nik: data.nik, + email: data.email, + phone: data.phone + }, + }); + + if (cek == 0) { + const users = await prisma.user.create({ + data: { + nik: data.nik, + name: data.name, + phone: data.phone, + email: data.email, + gender: data.gender, + idGroup: data.idGroup, + idVillage: village, + idPosition: data.idPosition, + idUserRole: data.idUserRole, + }, + select: { + id: true, + nik: true, + name: true, + phone: true, + email: true, + gender: true, + }, + }); + + // create log user + const log = await createLogUser({ act: 'CREATE', desc: 'User membuat data user baru', table: 'user', data: users.id }) + + return Response.json({ success: true, message: 'Sukses membuat user' }, { status: 200 }); + } else { + return Response.json({ success: false, message: "User sudah ada" }, { status: 400 }); + } + + + + } catch (error) { + console.error(error); + return Response.json({ success: false, message: "Internal Server Error" }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/module/user/member/index.ts b/src/module/user/member/index.ts index 932f79f..2eb952b 100644 --- a/src/module/user/member/index.ts +++ b/src/module/user/member/index.ts @@ -1,7 +1,7 @@ -import ViewCreateMember from "./view/view_create_member"; -import ViewDetailMember from "./view/view_detail_member"; -import ViewEditMember from "./view/view_edit_member"; -import ViewListMember from "./view/view_list_member"; +import ViewCreateMember from "./ui/view_create_member"; +import ViewDetailMember from "./ui/view_detail_member"; +import ViewEditMember from "./ui/view_edit_member"; +import ViewListMember from "./ui/view_list_member"; export { ViewListMember } export { ViewCreateMember } diff --git a/src/module/user/member/lib/api_member.ts b/src/module/user/member/lib/api_member.ts new file mode 100644 index 0000000..2e2ff84 --- /dev/null +++ b/src/module/user/member/lib/api_member.ts @@ -0,0 +1,64 @@ +import { IEditDataMember, IFormMember, IStatusmember } from "./type_member"; + +export const funGetAllmember = async (path?: string) => { + const response = await fetch(`/api/member${(path) ? path : ''}`, { next: { tags: ['member'] } }); + return await response.json().catch(() => null); +} + + +export const funGetOneMember = async (path: string) => { + const response = await fetch(`/api/member/${path}`); + return await response.json().catch(() => null); +} + +export const funCreateMember = async (data: IFormMember) => { + + if (data.name.length < 3) + return { success: false, message: 'Minimal 3 karakter' } + if (data.email.length < 3) + return { success: false, message: 'Minimal 3 karakter' } + + if (data.phone.length < 10) + return { success: false, message: 'Minimal 10 karakter' } + + if (data.nik.length == 16) + return { success: false, message: 'NIK harus 16 karakter' } + + const response = await fetch("/api/member", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + + +export const funEditStatusMember = async (path: string, data: IStatusmember) => { + + const response = await fetch(`/api/member/${path}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + + +export const funEditMember = async (path: string, data: IEditDataMember) => { + + if (data.name.length < 3) + return { success: false, message: 'Minimal 3 karakter' } + + const response = await fetch(`/api/member/${path}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} diff --git a/src/module/user/member/lib/type_member.ts b/src/module/user/member/lib/type_member.ts new file mode 100644 index 0000000..9128a22 --- /dev/null +++ b/src/module/user/member/lib/type_member.ts @@ -0,0 +1,49 @@ +export interface IListMember { + id: string, + isActive: boolean + nik: string, + name: string, + phone: string, + email: string, + gender: string, + group: string, + position: string, +} + +export interface IFormMember { + nik: string; + name: string; + phone: string; + email: string; + gender: string; + idGroup: string; + idPosition: string; + idUserRole: string; +} + +export interface IStatusmember { + isActive: boolean; + } + +// EDIT MEMBER +export interface IEditDataMember { + id: string; + nik: string; + name: string; + phone: string; + email: string; + gender: string; + idGroup: string; + idPosition: string; + idUserRole: string; + } + + export interface IDataPositionMember { + id: string; + name: string; + }; + + export interface IDataROleMember { + id: string; + name: string; + } \ No newline at end of file diff --git a/src/module/user/member/component/create_member.tsx b/src/module/user/member/ui/create_member.tsx similarity index 100% rename from src/module/user/member/component/create_member.tsx rename to src/module/user/member/ui/create_member.tsx diff --git a/src/module/user/member/component/ui/drawer_detail_member.tsx b/src/module/user/member/ui/drawer_detail_member.tsx similarity index 100% rename from src/module/user/member/component/ui/drawer_detail_member.tsx rename to src/module/user/member/ui/drawer_detail_member.tsx diff --git a/src/module/user/member/component/ui/drawer_list_member.tsx b/src/module/user/member/ui/drawer_list_member.tsx similarity index 100% rename from src/module/user/member/component/ui/drawer_list_member.tsx rename to src/module/user/member/ui/drawer_list_member.tsx diff --git a/src/module/user/member/component/edit_member.tsx b/src/module/user/member/ui/edit_member.tsx similarity index 100% rename from src/module/user/member/component/edit_member.tsx rename to src/module/user/member/ui/edit_member.tsx diff --git a/src/module/user/member/component/list_member.tsx b/src/module/user/member/ui/list_member.tsx similarity index 96% rename from src/module/user/member/component/list_member.tsx rename to src/module/user/member/ui/list_member.tsx index 33326b8..04076e9 100644 --- a/src/module/user/member/component/list_member.tsx +++ b/src/module/user/member/ui/list_member.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { HiMagnifyingGlass, HiMiniUser } from 'react-icons/hi2'; import { IoMdCheckmarkCircleOutline } from 'react-icons/io'; import { IoCloseCircleOutline } from 'react-icons/io5'; -import TabListMember from './ui/tab_list_member'; +import TabListMember from './tab_list_member'; export default function ListMember() { const iconStyle = { width: rem(20), height: rem(20) }; diff --git a/src/module/user/member/component/ui/navbar_create_member.tsx b/src/module/user/member/ui/navbar_create_member.tsx similarity index 100% rename from src/module/user/member/component/ui/navbar_create_member.tsx rename to src/module/user/member/ui/navbar_create_member.tsx diff --git a/src/module/user/member/component/ui/navbar_detail_member.tsx b/src/module/user/member/ui/navbar_detail_member.tsx similarity index 100% rename from src/module/user/member/component/ui/navbar_detail_member.tsx rename to src/module/user/member/ui/navbar_detail_member.tsx diff --git a/src/module/user/member/component/ui/navbar_edit_member.tsx b/src/module/user/member/ui/navbar_edit_member.tsx similarity index 100% rename from src/module/user/member/component/ui/navbar_edit_member.tsx rename to src/module/user/member/ui/navbar_edit_member.tsx diff --git a/src/module/user/member/component/ui/navbar_list_member.tsx b/src/module/user/member/ui/navbar_list_member.tsx similarity index 100% rename from src/module/user/member/component/ui/navbar_list_member.tsx rename to src/module/user/member/ui/navbar_list_member.tsx diff --git a/src/module/user/member/component/ui/tab_list_member.tsx b/src/module/user/member/ui/tab_list_member.tsx similarity index 100% rename from src/module/user/member/component/ui/tab_list_member.tsx rename to src/module/user/member/ui/tab_list_member.tsx diff --git a/src/module/user/member/view/view_create_member.tsx b/src/module/user/member/ui/view_create_member.tsx similarity index 66% rename from src/module/user/member/view/view_create_member.tsx rename to src/module/user/member/ui/view_create_member.tsx index f6f77d0..6d938c9 100644 --- a/src/module/user/member/view/view_create_member.tsx +++ b/src/module/user/member/ui/view_create_member.tsx @@ -1,14 +1,14 @@ import { Box } from "@mantine/core"; -import NavbarCreateMember from "../component/ui/navbar_create_member"; +import NavbarCreateMember from "./navbar_create_member"; import { LayoutNavbarNew, WARNA } from "@/module/_global"; -import CreateMember from "../component/create_member"; +import CreateMember from "./create_member"; export default function ViewCreateMember() { return ( {/* */} } /> - + ) } \ No newline at end of file diff --git a/src/module/user/member/view/view_detail_member.tsx b/src/module/user/member/ui/view_detail_member.tsx similarity index 73% rename from src/module/user/member/view/view_detail_member.tsx rename to src/module/user/member/ui/view_detail_member.tsx index 28b4a04..0e4b70e 100644 --- a/src/module/user/member/view/view_detail_member.tsx +++ b/src/module/user/member/ui/view_detail_member.tsx @@ -1,8 +1,8 @@ -import { Box, Group, Text } from "@mantine/core"; +import { Box, Group, Text } from "@mantine/core"; import { FaSquarePhone } from "react-icons/fa6"; import { MdEmail } from "react-icons/md"; import { RiIdCardFill } from "react-icons/ri"; -import NavbarDetailMember from "../component/ui/navbar_detail_member"; +import NavbarDetailMember from "./navbar_detail_member"; import { IoMaleFemale } from "react-icons/io5"; export default function ViewDetailMember({ data }: { data: string }) { diff --git a/src/module/user/member/view/view_edit_member.tsx b/src/module/user/member/ui/view_edit_member.tsx similarity index 64% rename from src/module/user/member/view/view_edit_member.tsx rename to src/module/user/member/ui/view_edit_member.tsx index 951313f..82d8edd 100644 --- a/src/module/user/member/view/view_edit_member.tsx +++ b/src/module/user/member/ui/view_edit_member.tsx @@ -1,10 +1,10 @@ import { LayoutNavbarHome, LayoutNavbarNew, WARNA } from "@/module/_global"; import { Box, Stack, TextInput, Button } from "@mantine/core"; import { HiUser } from "react-icons/hi2"; -import NavbarEditMember from "../component/ui/navbar_edit_member"; -import EditMember from "../component/edit_member"; +import NavbarEditMember from "./navbar_edit_member"; +import EditMember from "./edit_member"; -export default function ViewEditMember({data}: {data: string}) { +export default function ViewEditMember({ data }: { data: string }) { return ( } /> diff --git a/src/module/user/member/view/view_list_member.tsx b/src/module/user/member/ui/view_list_member.tsx similarity index 60% rename from src/module/user/member/view/view_list_member.tsx rename to src/module/user/member/ui/view_list_member.tsx index 4b1bb6b..bab8f16 100644 --- a/src/module/user/member/view/view_list_member.tsx +++ b/src/module/user/member/ui/view_list_member.tsx @@ -1,6 +1,6 @@ import { Box } from "@mantine/core"; -import NavbarListMember from "../component/ui/navbar_list_member"; -import ListMember from "../component/list_member"; +import NavbarListMember from "./navbar_list_member"; +import ListMember from "./list_member"; export default function ViewListMember() { return (