From 61df9959c197400847e3def47df7b64db2a8822e Mon Sep 17 00:00:00 2001 From: lukman Date: Fri, 30 Aug 2024 17:18:05 +0800 Subject: [PATCH] feat : update user --- src/app/api/user/[id]/route.ts | 72 ++++-- src/app/api/user/route.ts | 221 +++++++++--------- .../calender/ui/date_event_division.tsx | 2 +- src/module/user/member/lib/api_member.ts | 7 +- src/module/user/member/lib/type_member.ts | 85 +++---- src/module/user/member/ui/edit_member.tsx | 59 +++-- .../user/member/ui/navbar_detail_member.tsx | 2 +- src/module/user/member/ui/tab_list_member.tsx | 9 +- 8 files changed, 258 insertions(+), 199 deletions(-) diff --git a/src/app/api/user/[id]/route.ts b/src/app/api/user/[id]/route.ts index dc2ba9f..1151a0b 100644 --- a/src/app/api/user/[id]/route.ts +++ b/src/app/api/user/[id]/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 ONE MEMBER / USER export async function GET(request: Request, context: { params: { id: string } }) { @@ -24,6 +26,7 @@ export async function GET(request: Request, context: { params: { id: string } }) phone: true, email: true, gender: true, + img: true, idGroup: true, isActive: true, idPosition: true, @@ -131,12 +134,27 @@ export async function PUT(request: Request, context: { params: { id: string } }) return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); } const { id } = context.params; - const data = await request.json(); + console.log(id) + + const body = await request.formData() + const file = body.get("file") as File + const data = body.get("data") + const { + name, + email, + phone, + nik, + gender, + idGroup, + idPosition, + idUserRole + } = JSON.parse(data as string) + // const data = await request.json(); const cek = await prisma.user.count({ where: { - nik: data.nik, - email: data.email, - phone: data.phone, + nik: nik, + email: email, + phone: phone, NOT: { id: id } @@ -149,22 +167,46 @@ export async function PUT(request: Request, context: { params: { id: string } }) 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, - }, + nik: nik, + name: name, + phone: "62" + phone, + email: email, + gender: gender, + idGroup: idGroup, + idPosition: idPosition, + idUserRole: idUserRole, + }, + select: { + img: true + } }); + if (String(file) != "undefined" && String(file) != "null") { + fs.unlink(`./public/image/user/${updates.img}`, (err) => { }) + const root = path.join(process.cwd(), "./public/image/user/"); + const fExt = file.name.split(".").pop() + const fileName = id + '.' + fExt; + const filePath = path.join(root, fileName); + + // Konversi ArrayBuffer ke Buffer + const buffer = Buffer.from(await file.arrayBuffer()); + fs.writeFileSync(filePath, buffer); + + await prisma.user.update({ + where: { + id: id + }, + data: { + img: fileName + } + }) + } + // create log user - const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data user', table: 'user', data: data.id }) + const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data user', table: 'user', data: user.id }) return Response.json( - { success: true, message: "Sukses Update User", updates }, + { success: true, message: "Sukses Update User" }, { status: 200 } ); } else { diff --git a/src/app/api/user/route.ts b/src/app/api/user/route.ts index 1d7f3b0..3faba9d 100644 --- a/src/app/api/user/route.ts +++ b/src/app/api/user/route.ts @@ -6,121 +6,122 @@ 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 == 'false' ? false : true, - 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", "Position" ]), - group: v.Group.name, - position: v.Position.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 }); + 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 == 'false' ? false : true, + 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, + img: true, + Position: { + select: { + name: true, + }, + }, + Group: { + select: { + name: true, + }, + }, + }, + }); + + const allData = users.map((v: any) => ({ + ..._.omit(v, ["Group", "Position"]), + group: v.Group.name, + position: v.Position.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 { + 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 }); - } + 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/calender/ui/date_event_division.tsx b/src/module/calender/ui/date_event_division.tsx index bf609b7..716721b 100644 --- a/src/module/calender/ui/date_event_division.tsx +++ b/src/module/calender/ui/date_event_division.tsx @@ -82,7 +82,7 @@ export default function DateEventDivision() { const muncul = isListTgl.includes(coba) return ( - +
{day}
); diff --git a/src/module/user/member/lib/api_member.ts b/src/module/user/member/lib/api_member.ts index 4bfdb59..461c735 100644 --- a/src/module/user/member/lib/api_member.ts +++ b/src/module/user/member/lib/api_member.ts @@ -52,13 +52,10 @@ export const funEditStatusMember = async (path: string, data: IStatusmember) => } -export const funEditMember = async (path: string, data: IEditDataMember) => { +export const funEditMember = async (path: string, data: FormData) => { const response = await fetch(`/api/user/${path}`, { method: "PUT", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(data), + body: 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 index 7119f24..3d3f2ba 100644 --- a/src/module/user/member/lib/type_member.ts +++ b/src/module/user/member/lib/type_member.ts @@ -1,53 +1,54 @@ export interface IListMember { - id: string, - name: string, - nik: string, - email: string, - phone: string, - gender: string, - position: string, - group: string, - isActive: boolean + id: string, + name: string, + nik: string, + email: string, + phone: string, + gender: string, + position: string, + group: string, + img: string, + isActive: boolean } -export interface IFormMember { - nik: string; - name: string; - phone: string; - email: string; - gender: string; - idGroup: string; - idPosition: string; - idUserRole: 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; - } + 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; - } +export interface IEditDataMember { + id: string; + nik: string; + name: string; + phone: string; + email: string; + gender: string; + idGroup: string; + idPosition: string; + idUserRole: string; +} -export interface IMember{ +export interface IDataPositionMember { + id: string; + name: string; +}; + +export interface IDataROleMember { + id: string; + name: string; +} + +export interface IMember { id: string } \ No newline at end of file diff --git a/src/module/user/member/ui/edit_member.tsx b/src/module/user/member/ui/edit_member.tsx index 8fbe283..526d3ce 100644 --- a/src/module/user/member/ui/edit_member.tsx +++ b/src/module/user/member/ui/edit_member.tsx @@ -3,15 +3,17 @@ import { WARNA } from "@/module/_global"; import LayoutModal from "@/module/_global/layout/layout_modal"; import { funGetAllGroup, IDataGroup } from "@/module/group"; import { funGetAllPosition } from "@/module/position/lib/api_position"; -import { Box, Button, Select, Stack, Text, TextInput } from "@mantine/core"; +import { Avatar, Box, Button, Indicator, Select, Stack, Text, TextInput } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; import { useRouter } from "next/navigation"; -import { useState } from "react"; +import { useRef, useState } from "react"; import toast from "react-hot-toast"; import { HiUser } from "react-icons/hi2"; import { IDataPositionMember, IDataROleMember, IEditDataMember, IFormMember } from "../lib/type_member"; import { funEditMember, funGetOneMember, funGetRoleUser } from "../lib/api_member"; import _ from "lodash"; +import { Dropzone } from "@mantine/dropzone"; +import { FaCamera } from "react-icons/fa6"; export default function EditMember({ id }: { id: string }) { @@ -20,6 +22,9 @@ export default function EditMember({ id }: { id: string }) { const [listGroup, setListGorup] = useState([]) const [listPosition, setListPosition] = useState([]) const [listUserRole, setListUserRole] = useState([]) + const [imgForm, setImgForm] = useState() + const openRef = useRef<() => void>(null) + const [img, setIMG] = useState() const [touched, setTouched] = useState({ nik: false, name: false, @@ -61,6 +66,7 @@ export default function EditMember({ id }: { id: string }) { const res = await funGetOneMember(id) setData(res.data) getAllPosition(res.data?.idGroup) + setIMG(`/api/file/img?cat=user&file=${res.data.img}`) } catch (error) { console.error(error) } @@ -110,17 +116,11 @@ export default function EditMember({ id }: { id: string }) { return } if (val) { - const res = await funEditMember(id, { - id: data.id, - nik: data.nik, - name: data.name, - phone: data.phone, - email: data.email, - gender: data.gender, - idGroup: data.idGroup, - idPosition: data.idPosition, - idUserRole: data.idUserRole - }) + const fd = new FormData() + fd.append("file", imgForm) + fd.append("data", JSON.stringify(data)) + + const res = await funEditMember(id, fd) if (res.success) { toast.success(res.message) @@ -144,12 +144,30 @@ export default function EditMember({ id }: { id: string }) { pt={30} px={20} > - - - + { + 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?.()}> + +