diff --git a/src/app/(application)/layout.tsx b/src/app/(application)/layout.tsx index 75575d1..95b566a 100644 --- a/src/app/(application)/layout.tsx +++ b/src/app/(application)/layout.tsx @@ -1,17 +1,18 @@ -import { pwd_key_config } from "@/module/_global" -import { funDetectCookies } from "@/module/auth" -import { unsealData } from "iron-session" +import { WrapLayout } from "@/module/_global" +import { funDetectCookies, funGetUserByCookies } from "@/module/auth" import _ from "lodash" -import { cookies } from "next/headers" import { redirect } from "next/navigation" export default async function Layout({ children }: { children: React.ReactNode }) { const cookies = await funDetectCookies() if (!cookies) return redirect('/') + const user = await funGetUserByCookies() return ( <> - {children} + + {children} + ); } \ No newline at end of file diff --git a/src/app/api/position/[id]/route.ts b/src/app/api/position/[id]/route.ts index f36d2c3..5d0d165 100644 --- a/src/app/api/position/[id]/route.ts +++ b/src/app/api/position/[id]/route.ts @@ -1,5 +1,6 @@ import { prisma } from "@/module/_global"; import { funGetUserByCookies } from "@/module/auth"; +import { createLogUser } from "@/module/user"; import { revalidatePath } from "next/cache"; import { NextResponse } from "next/server"; @@ -80,6 +81,8 @@ export async function DELETE(request: Request, context: { params: { id: string } }, }); + // create log user + const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate status data jabatan', table: 'position', data: id }) return NextResponse.json( { success: true, message: "Berhasil mengubah status jabatan" }, { status: 200 } @@ -104,8 +107,12 @@ export async function PUT(request: Request, context: { params: { id: string } }) where: { name: data.name, idGroup: data.idGroup, + NOT: { + id: id + } }, }); + if (cek == 0) { const positions = await prisma.position.update({ where: { @@ -113,10 +120,13 @@ export async function PUT(request: Request, context: { params: { id: string } }) }, data: { name: data.name, - idGroup: data.idGroup, + // idGroup: data.idGroup, }, }); - return NextResponse.json({ success: true, message: "Berhasil mengedit jabatan", positions, }, { status: 200 }); + + // create log user + const log = await createLogUser({ act: 'UPDATE', desc: 'User mengupdate data jabatan', table: 'position', data: id }) + return NextResponse.json({ success: true, message: "Berhasil mengedit jabatan", }, { status: 200 }); } else { return NextResponse.json( { success: false, message: "Jabatan sudah ada" }, diff --git a/src/app/api/position/route.ts b/src/app/api/position/route.ts index 37dde56..9112a5f 100644 --- a/src/app/api/position/route.ts +++ b/src/app/api/position/route.ts @@ -1,5 +1,6 @@ import { prisma } from "@/module/_global"; import { funGetUserByCookies } from "@/module/auth"; +import { createLogUser } from "@/module/user"; import _ from "lodash"; import { revalidatePath, revalidateTag } from "next/cache"; import { NextResponse } from "next/server"; @@ -21,9 +22,9 @@ export async function GET(request: Request) { if (idGroup == "null" || idGroup == undefined) { grup = user.idGroup - } else { + } else { grup = idGroup - } + } const cek = await prisma.group.count({ where: { @@ -36,10 +37,20 @@ export async function GET(request: Request) { return NextResponse.json({ success: false, message: "Gagal mendapatkan jabatan, data tidak ditemukan", }, { status: 404 }); } + const filter = await prisma.group.findUnique({ + where: { + id: grup + }, + select: { + id: true, + name: true + } + }) + const positions = await prisma.position.findMany({ where: { idGroup: grup, - isActive: (active == "true" ? true : false), + isActive: active == 'false' ? false : true, name: { contains: (name == undefined || name == null) ? "" : name, mode: "insensitive" @@ -62,7 +73,7 @@ export async function GET(request: Request) { group: v.Group.name })) - return NextResponse.json({ success: true, message: "Berhasil mendapatkan jabatan", data: allData, }, { status: 200 }); + return NextResponse.json({ success: true, message: "Berhasil mendapatkan jabatan", data: allData, filter }, { status: 200 }); } catch (error) { console.error(error); return NextResponse.json({ success: false, message: "Gagal mendapatkan jabatan, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); @@ -78,18 +89,26 @@ 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 { name, idGroup } = await request.json(); + + let groupFix = idGroup + + if (groupFix == null || groupFix == undefined || groupFix == "") { + groupFix = user.idGroup + } + + const cek = await prisma.position.count({ where: { - name: data.name, - idGroup: data.idGroup, + name: name, + idGroup: groupFix, }, }); if (cek == 0) { const positions = await prisma.position.create({ data: { - name: data.name, - idGroup: data.idGroup, + name: name, + idGroup: groupFix, }, select: { id: true, @@ -102,6 +121,9 @@ export async function POST(request: Request) { revalidatePath('/position?active=true', 'page') revalidateTag('position') + // create log user + const log = await createLogUser({ act: 'CREATE', desc: 'User membuat data jabatan baru', table: 'position', data: positions.id }) + return NextResponse.json({ success: true, message: "Berhasil menambahkan jabatan", positions, }, { status: 200 }); } else { return NextResponse.json( diff --git a/src/app/api/user/route.ts b/src/app/api/user/route.ts index 3faba9d..bf6ac85 100644 --- a/src/app/api/user/route.ts +++ b/src/app/api/user/route.ts @@ -22,6 +22,16 @@ export async function GET(request: Request) { fixGroup = idGroup } + const filter = await prisma.group.findUnique({ + where: { + id: fixGroup + }, + select: { + id: true, + name: true + } + }) + const users = await prisma.user.findMany({ where: { @@ -60,7 +70,7 @@ export async function GET(request: Request) { position: v.Position.name })) - return NextResponse.json({ success: true, message: "Berhasil member", data: allData, }, { status: 200 }); + return NextResponse.json({ success: true, message: "Berhasil member", data: allData, filter }, { 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 }); @@ -77,7 +87,13 @@ export async function POST(request: Request) { return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); } const data = await request.json(); - const village = "desa1" + const village = String(user.idVillage) + + let groupFix = data.idGroup + + if (groupFix == null || groupFix == undefined || groupFix == "") { + groupFix = user.idGroup + } const cek = await prisma.user.count({ where: { @@ -95,18 +111,13 @@ export async function POST(request: Request) { phone: data.phone, email: data.email, gender: data.gender, - idGroup: data.idGroup, + idGroup: groupFix, idVillage: village, idPosition: data.idPosition, idUserRole: data.idUserRole, }, select: { - id: true, - nik: true, - name: true, - phone: true, - email: true, - gender: true, + id: true }, }); diff --git a/src/module/_global/bin/val_global.ts b/src/module/_global/bin/val_global.ts index 17bfaca..4a5dc97 100644 --- a/src/module/_global/bin/val_global.ts +++ b/src/module/_global/bin/val_global.ts @@ -1 +1,4 @@ -export const pwd_key_config = "fchgvjknlmdfnbvghhujlaknsdvjbhknlkmsdbdyu567t8y9u30r4587638y9uipkoeghjvuyi89ipkoefmnrjbhtiu4or9ipkoemnjfbhjiuoijdklnjhbviufojkejnshbiuojijknehgruyu" \ No newline at end of file +import { hookstate } from "@hookstate/core" + +export const pwd_key_config = "fchgvjknlmdfnbvghhujlaknsdvjbhknlkmsdbdyu567t8y9u30r4587638y9uipkoeghjvuyi89ipkoefmnrjbhtiu4or9ipkoemnjfbhjiuoijdklnjhbviufojkejnshbiuojijknehgruyu" +export const globalRole = hookstate('') \ No newline at end of file diff --git a/src/module/_global/components/wrap_layout.tsx b/src/module/_global/components/wrap_layout.tsx new file mode 100644 index 0000000..da1831a --- /dev/null +++ b/src/module/_global/components/wrap_layout.tsx @@ -0,0 +1,17 @@ +'use client' +import { useHookstate } from "@hookstate/core"; +import { globalRole } from "../bin/val_global"; +import { useShallowEffect } from "@mantine/hooks"; + +export default function WrapLayout({ children, role }: { children: React.ReactNode, role: any }) { + const roleLogin = useHookstate(globalRole) + + useShallowEffect(() => { + roleLogin.set(role) + }, []) + return ( + <> + {children} + + ); +} \ No newline at end of file diff --git a/src/module/_global/index.ts b/src/module/_global/index.ts index ca87c71..bde645d 100644 --- a/src/module/_global/index.ts +++ b/src/module/_global/index.ts @@ -1,10 +1,11 @@ import prisma from "./bin/prisma"; -import { pwd_key_config } from "./bin/val_global"; +import { globalRole, pwd_key_config } from "./bin/val_global"; import SkeletonDetailDiscussionComment from "./components/skeleton_detail_discussion_comment"; import SkeletonDetailDiscussionMember from "./components/skeleton_detail_discussion_member"; import SkeletonDetailListTugasTask from "./components/skeleton_detail_list_tugas_task"; import SkeletonDetailProfile from "./components/skeleton_detail_profile"; import SkeletonSingle from "./components/skeleton_single"; +import WrapLayout from "./components/wrap_layout"; import { WARNA } from "./fun/WARNA"; import LayoutDrawer from "./layout/layout_drawer"; import LayoutIconBack from "./layout/layout_icon_back"; @@ -31,3 +32,5 @@ export { SkeletonDetailDiscussionMember } export { SkeletonDetailProfile } export { SkeletonDetailListTugasTask } export { LayoutModalViewFile } +export { globalRole } +export { WrapLayout } diff --git a/src/module/_global/view/view_filter.tsx b/src/module/_global/view/view_filter.tsx index 6a29917..85e9c57 100644 --- a/src/module/_global/view/view_filter.tsx +++ b/src/module/_global/view/view_filter.tsx @@ -1,23 +1,21 @@ 'use client' import { Box, Group, Divider, Button, Text, Skeleton, rem } from "@mantine/core"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { FaCheck } from "react-icons/fa6"; import { WARNA } from "../fun/WARNA"; import LayoutNavbarNew from "../layout/layout_navbar_new"; -import { useRouter } from "next/navigation"; +import { useRouter, useSearchParams } from "next/navigation"; import { funGetAllGroup, IDataGroup } from "@/module/group"; import { useShallowEffect } from "@mantine/hooks"; import toast from "react-hot-toast"; export default function ViewFilter({ linkFilter }: { linkFilter: string }) { - const [selectedFilter, setSelectedFilter] = useState(null); + const [selectedFilter, setSelectedFilter] = useState(''); const [checked, setChecked] = useState([]); - const [searchParams, setSearchParams] = useState({ groupId: '' }); const [loading, setLoading] = useState(true) + const searchParams = useSearchParams() + const group = searchParams.get('group') - const handleFilterClick = (id: string) => { - setSelectedFilter(id); - }; async function getAllGroupFilter() { try { @@ -37,15 +35,14 @@ export default function ViewFilter({ linkFilter }: { linkFilter: string }) { } } - useEffect(() => { - if (selectedFilter) { - setSearchParams({ groupId: selectedFilter }); - } - }, [selectedFilter]); + useShallowEffect(() => { + setSelectedFilter(group) + }, [group]); + useShallowEffect(() => { getAllGroupFilter(); - }, [searchParams.groupId]); + }, []); const router = useRouter() @@ -71,7 +68,7 @@ export default function ViewFilter({ linkFilter }: { linkFilter: string }) { justify="space-between" align="center" mb={10} - onClick={() => handleFilterClick(filter.id)} + onClick={() => setSelectedFilter(filter.id)} > {filter.name} diff --git a/src/module/home/ui/view_detail_feature.tsx b/src/module/home/ui/view_detail_feature.tsx index 6c46c01..00dd94f 100644 --- a/src/module/home/ui/view_detail_feature.tsx +++ b/src/module/home/ui/view_detail_feature.tsx @@ -1,14 +1,16 @@ 'use client' -import { LayoutNavbarNew, WARNA } from '@/module/_global'; +import { globalRole, LayoutNavbarNew, WARNA } from '@/module/_global'; import { ActionIcon, Box, Center, SimpleGrid, Text } from '@mantine/core'; import React from 'react'; import { HiMiniUserGroup, HiMiniPresentationChartBar, HiMegaphone, HiSquares2X2, HiChevronLeft, HiUserGroup, HiUsers } from "react-icons/hi2"; import { PiUsersFourFill } from "react-icons/pi"; import { useRouter } from 'next/navigation'; import { FaUserTag, FaUserTie } from 'react-icons/fa6'; +import { useHookstate } from '@hookstate/core'; export default function ViewDetailFeature() { const router = useRouter() + const roleLogin = useHookstate(globalRole) return ( <> } /> @@ -73,7 +75,7 @@ export default function ViewDetailFeature() { Anggota - router.push('position?active=true')}> + router.push('/position')}>
Jabatan
- router.push('/group')}> -
- - - -
-
- Grup -
-
+ { + roleLogin.get() == "supadmin" && + router.push('/group')}> +
+ + + +
+
+ Grup +
+
+ } +
diff --git a/src/module/position/ui/drawer_detail_position.tsx b/src/module/position/ui/drawer_detail_position.tsx index 4d68fbb..e22376f 100644 --- a/src/module/position/ui/drawer_detail_position.tsx +++ b/src/module/position/ui/drawer_detail_position.tsx @@ -159,7 +159,7 @@ export default function DrawerDetailPosition({ onUpdated, id, isActive }: { : - ({ - value: data.id, - label: data.name, - })) - : [] - } - size="md" - radius={10} - mb={5} - withAsterisk - onChange={(val: any) => { - setListData({ - ...listData, - idGroup: val - }) - setTouched({ ...touched, idGroup: false }) - }} - styles={{ - input: { - color: WARNA.biruTua, - borderRadius: WARNA.biruTua, - borderColor: WARNA.biruTua, - }, - }} - error={ - touched.idGroup && ( - listData.idGroup == "" ? "Grup Tidak Boleh Kosong" : null - ) - } - onFocus={() => setTouched({ ...touched, idGroup: true })} - onBlur={() => setTouched({ ...touched, idGroup: true })} - /> + { + roleLogin.get() == "supadmin" && + ({ - value: data.id, - label: data.name, - })) - : [] - } - onChange={(val: any) => { - changeGrup(val); - setTouched({ ...touched, idGroup: false }) - }} - onBlur={() => setTouched({ ...touched, idGroup: true })} - error={ - touched.idGroup && ( - listData.idGroup == "" ? "Grup Tidak Boleh Kosong" : null - ) - } - /> + { + roleLogin.get() == "supadmin" && + diff --git a/src/module/user/member/ui/drawer_list_member.tsx b/src/module/user/member/ui/drawer_list_member.tsx index 92a79fa..071556e 100644 --- a/src/module/user/member/ui/drawer_list_member.tsx +++ b/src/module/user/member/ui/drawer_list_member.tsx @@ -1,12 +1,16 @@ -import { WARNA } from '@/module/_global'; +import { globalRole, WARNA } from '@/module/_global'; +import { useHookstate } from '@hookstate/core'; import { Box, Flex, SimpleGrid, Stack, Text } from '@mantine/core'; -import { useRouter } from 'next/navigation'; -import React, { useState } from 'react'; +import { useRouter, useSearchParams } from 'next/navigation'; +import React from 'react'; import { IoAddCircle } from "react-icons/io5"; import { RiFilter2Line } from 'react-icons/ri'; export default function DrawerListMember() { const router = useRouter() + const roleLogin = useHookstate(globalRole) + const searchParams = useSearchParams() + const group = searchParams.get('group') return ( @@ -29,20 +33,22 @@ export default function DrawerListMember() { Tambah Anggota - - { - router.push('/member?page=filter') - }} - > - - - - - Filter - - + { + roleLogin.get() === 'supadmin' && + { + router.push('/member?page=filter&group=' + group) + }} + > + + + + + Filter + + + } diff --git a/src/module/user/member/ui/tab_list_member.tsx b/src/module/user/member/ui/tab_list_member.tsx index 9173ae0..b66c399 100644 --- a/src/module/user/member/ui/tab_list_member.tsx +++ b/src/module/user/member/ui/tab_list_member.tsx @@ -1,15 +1,16 @@ -import { SkeletonSingle, WARNA } from "@/module/_global" -import { Box, Group, ActionIcon, Text, TextInput, Divider, Avatar, Grid } from "@mantine/core" +import { globalRole, SkeletonSingle, WARNA } from "@/module/_global" +import { Box, Text, TextInput, Divider, Avatar, Grid } from "@mantine/core" import { useShallowEffect } from "@mantine/hooks" import { useRouter, useSearchParams } from "next/navigation" -import { useEffect, useState } from "react" -import { HiMagnifyingGlass, HiMiniUser } from "react-icons/hi2" +import { useState } from "react" +import { HiMagnifyingGlass } from "react-icons/hi2" import { IListMember } from "../lib/type_member" import { funGetAllmember } from "../lib/api_member" import { funGetAllGroup, IDataGroup } from "@/module/group" import toast from "react-hot-toast" import _ from "lodash" +import { useHookstate } from "@hookstate/core" export default function TabListMember() { @@ -20,13 +21,20 @@ export default function TabListMember() { const [searchQuery, setSearchQuery] = useState('') const group = searchParams.get('group') const status = searchParams.get('active') + const roleLogin = useHookstate(globalRole) + const [nameGroup, setNameGroup] = useState('') async function getAllUser() { try { setLoading(true) const res = await funGetAllmember('?active=' + status + '&group=' + group + '&search=' + searchQuery) - setDataMember(res.data) + if (res.success) { + setDataMember(res.data) + setNameGroup(res.filter.name) + } else { + toast.error(res.message) + } } catch (error) { console.error(error) throw new Error("Error") @@ -39,31 +47,6 @@ export default function TabListMember() { getAllUser() }, [status, searchQuery]) - const [checked, setChecked] = useState([]); - - const groupNameMap = (groupId: string) => { - const groupName = checked.find((group) => group.id === groupId)?.name; - return groupName || '-'; - }; - - async function getAllGroupFilter() { - try { - const response = await funGetAllGroup('?active=true') - if (response.success) { - setChecked(response.data); - } else { - toast.error(response.message); - } - } catch (error) { - console.error(error); - toast.error("Gagal mendapatkan grup, coba lagi nanti"); - } - } - - useShallowEffect(() => { - getAllGroupFilter(); - }, []); - return ( <> @@ -92,7 +75,7 @@ export default function TabListMember() { )) : - {group && Filter by: {groupNameMap(group)}} + {roleLogin.get() == 'supadmin' && Filter by: {nameGroup}} {dataMember.length == 0 ? Tidak ada anggota @@ -107,7 +90,7 @@ export default function TabListMember() { + }} align="center">