From d23d579dd05fa9777ae38aa576c1aaa20b0bc9fe Mon Sep 17 00:00:00 2001 From: amel Date: Wed, 4 Sep 2024 17:16:25 +0800 Subject: [PATCH] upd: member Deskripsi: - pembatasan user role - tambah member - detail member - upload image member No Issues --- src/app/api/user/route.ts | 49 +++++++++-- src/module/user/lib/val_user.ts | 66 +++++++++++++++ src/module/user/member/lib/api_member.ts | 21 +---- src/module/user/member/ui/create_member.tsx | 83 ++++++++++++------- .../user/member/ui/navbar_detail_member.tsx | 23 +++-- .../user/member/ui/navbar_list_member.tsx | 8 +- 6 files changed, 183 insertions(+), 67 deletions(-) create mode 100644 src/module/user/lib/val_user.ts diff --git a/src/app/api/user/route.ts b/src/app/api/user/route.ts index bf6ac85..95fc943 100644 --- a/src/app/api/user/route.ts +++ b/src/app/api/user/route.ts @@ -3,6 +3,8 @@ import { funGetUserByCookies } from "@/module/auth"; import { createLogUser } from "@/module/user"; import _ from "lodash"; import { NextResponse } from "next/server"; +import path from "path"; +import fs from "fs"; // GET ALL MEMBER / USER export async function GET(request: Request) { @@ -86,7 +88,9 @@ export async function POST(request: Request) { if (user.id == undefined) { return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); } - const data = await request.json(); + const body = await request.formData() + const data = JSON.parse(body.get("data") as string) + const file = body.get("file") as File const village = String(user.idVillage) let groupFix = data.idGroup @@ -95,15 +99,26 @@ export async function POST(request: Request) { groupFix = user.idGroup } - const cek = await prisma.user.count({ + const cekNIK = await prisma.user.count({ + where: { + nik: data.nik + }, + }); + + const cekEmail = await prisma.user.count({ + where: { + email: data.email + }, + }); + + const cekPhone = await prisma.user.count({ where: { - nik: data.nik, - email: data.email, phone: data.phone }, }); - if (cek == 0) { + + if (cekNIK == 0 && cekEmail == 0 && cekPhone == 0) { const users = await prisma.user.create({ data: { nik: data.nik, @@ -121,6 +136,28 @@ export async function POST(request: Request) { }, }); + if (String(file) != "undefined" && String(file) != "null") { + const root = path.join(process.cwd(), "./public/image/user/"); + const fExt = file.name.split(".").pop() + const fileName = users.id + '.' + fExt; + const filePath = path.join(root, fileName); + + // Konversi ArrayBuffer ke Buffer + const buffer = Buffer.from(await file.arrayBuffer()); + + // Tulis file ke sistem + fs.writeFileSync(filePath, buffer); + + await prisma.user.update({ + where: { + id: users.id + }, + data: { + img: fileName + } + }) + } + // create log user const log = await createLogUser({ act: 'CREATE', desc: 'User membuat data user baru', table: 'user', data: users.id }) @@ -129,8 +166,6 @@ export async function POST(request: Request) { 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 }); diff --git a/src/module/user/lib/val_user.ts b/src/module/user/lib/val_user.ts new file mode 100644 index 0000000..ab0793c --- /dev/null +++ b/src/module/user/lib/val_user.ts @@ -0,0 +1,66 @@ +export const valueRoleUser = + [ + { + login: "supadmin", + data: [ + { + id: "cosupadmin", + name: "Wakil Super Admin" + }, + { + id: "admin", + name: "Admin" + }, + { + id: "coadmin", + name: "Wakil Admin" + }, + { + id: "user", + name: "User" + }, + ] + }, + { + login: "cosupadmin", + data: [ + { + id: "admin", + name: "Admin" + }, + { + id: "coadmin", + name: "Wakil Admin" + }, + { + id: "user", + name: "User" + }, + ], + }, + { + login: "admin", + data: [ + { + id: "coadmin", + name: "Wakil Admin" + }, + { + id: "user", + name: "User" + }, + ], + }, + { + login: "coadmin", + data: [ + { + id: "user", + name: "User" + }, + ], + } + ] + + + diff --git a/src/module/user/member/lib/api_member.ts b/src/module/user/member/lib/api_member.ts index 461c735..a637cb6 100644 --- a/src/module/user/member/lib/api_member.ts +++ b/src/module/user/member/lib/api_member.ts @@ -5,7 +5,7 @@ export const funGetAllmember = async (path?: string) => { return await response.json().catch(() => null); } -export const funGetRoleUser= async (path?: string) => { +export const funGetRoleUser = async (path?: string) => { const response = await fetch(`/api/role-user${(path) ? path : ''}`, { next: { tags: ['member'] } }); return await response.json().catch(() => null); } @@ -15,25 +15,10 @@ export const funGetOneMember = async (path: string) => { return await response.json().catch(() => null); } -export const funCreateMember = async (data: IFormMember) => { - - if (data.name.length < 3) - return { success: false, message: 'Name minimal 3 karakter' } - if (data.email.length < 3) - return { success: false, message: 'Email minimal 3 karakter' } - - if (data.phone.length < 10) - return { success: false, message: 'Phone minimal 10 karakter' } - - if (data.nik.length < 16) - return { success: false, message: 'NIK harus 16 karakter' } - +export const funCreateMember = async (data: FormData) => { const response = await fetch("/api/user", { method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(data), + body: data, }); return await response.json().catch(() => null); } diff --git a/src/module/user/member/ui/create_member.tsx b/src/module/user/member/ui/create_member.tsx index 72c35dd..48873f3 100644 --- a/src/module/user/member/ui/create_member.tsx +++ b/src/module/user/member/ui/create_member.tsx @@ -2,18 +2,20 @@ import { globalRole, WARNA } from "@/module/_global"; import LayoutModal from "@/module/_global/layout/layout_modal"; import { funGetAllGroup, IDataGroup } from "@/module/group"; -import { Box, Button, rem, Select, Stack, Text, TextInput } from "@mantine/core"; +import { Avatar, Box, Button, Indicator, rem, Select, Stack, Text, TextInput } from "@mantine/core"; import { useRouter } from "next/navigation"; -import { useEffect, useState } from "react"; +import { useRef, useState } from "react"; import toast from "react-hot-toast"; -import { HiUser } from "react-icons/hi2"; import { IDataPositionMember, IDataROleMember } from "../lib/type_member"; import { funGetAllPosition } from "@/module/position/lib/api_position"; -import { funCreateMember, funGetRoleUser } from "../lib/api_member"; +import { funCreateMember } from "../lib/api_member"; import _ from "lodash"; import { useHookstate } from "@hookstate/core"; import { useShallowEffect } from "@mantine/hooks"; import { funGetUserByCookies } from "@/module/auth"; +import { valueRoleUser } from "../../lib/val_user"; +import { FaCamera } from "react-icons/fa6"; +import { Dropzone } from "@mantine/dropzone"; export default function CreateMember() { const router = useRouter(); @@ -22,7 +24,9 @@ export default function CreateMember() { const [listPosition, setListPosition] = useState([]); const [listUserRole, setListUserRole] = useState([]); const roleLogin = useHookstate(globalRole) - const [groupLogin, setGroupLogin] = useState(""); + const [img, setIMG] = useState() + const [imgForm, setImgForm] = useState() + const openRef = useRef<() => void>(null) const [touched, setTouched] = useState({ nik: false, name: false, @@ -62,8 +66,10 @@ export default function CreateMember() { async function getLogin() { try { const res = await funGetUserByCookies(); - setGroupLogin(String(res.idGroup)); - getAllPosition(res.idGroup); + if (roleLogin.get() != "supadmin") { + getAllPosition(res.idGroup) + } + } catch (error) { console.error(error); } @@ -84,8 +90,7 @@ export default function CreateMember() { async function getAllUserRole() { try { - const res = await funGetRoleUser(); - setListUserRole(res.data); + setListUserRole(valueRoleUser.filter((v) => v.login == roleLogin.get())[0]?.data); } catch (error) { console.error(error); } @@ -108,16 +113,21 @@ export default function CreateMember() { return; } if (val) { - const res = await funCreateMember({ - nik: listData.nik, - name: listData.name, - phone: listData.phone, - email: listData.email, - gender: listData.gender, - idGroup: listData.idGroup, - idPosition: listData.idPosition, - idUserRole: listData.idUserRole, - }); + const fd = new FormData() + fd.append("file", imgForm) + fd.append("data", JSON.stringify( + { + nik: listData.nik, + name: listData.name, + phone: listData.phone, + email: listData.email, + gender: listData.gender, + idGroup: listData.idGroup, + idPosition: listData.idPosition, + idUserRole: listData.idUserRole, + } + )) + const res = await funCreateMember(fd); if (res.success) { toast.success(res.message); setModal(false); @@ -137,26 +147,37 @@ export default function CreateMember() { useShallowEffect(() => { getAllGroup(); getAllUserRole(); - - if (roleLogin.get() != "supadmin") { - getLogin() - } + getLogin() }, []); return ( - { + if (!files || _.isEmpty(files)) + return toast.error('Tidak ada gambar yang dipilih') + setImgForm(files[0]) + const buffer = URL.createObjectURL(new Blob([new Uint8Array(await files[0].arrayBuffer())])) + setIMG(buffer) + }} + activateOnClick={false} + maxSize={1 * 1024 ** 2} + accept={['image/png', 'image/jpeg', 'image/heic']} + onReject={(files) => { + return toast.error('File yang diizinkan: .png, .jpg, dan .heic dengan ukuran maksimal 1 MB') }} > - - + + } size={40} onClick={() => openRef.current?.()}> + + { roleLogin.get() == "supadmin" &&