fitur: divisi
Deskripsi: - tambah divisi No Issues
This commit is contained in:
@@ -38,4 +38,5 @@ export const API_ADDRESS = {
|
||||
|
||||
// Division
|
||||
"apiGetAllDivision": "/api/division/get?path=get-all-division",
|
||||
"apiCreateDivision": "/api/division/post?path=create-division",
|
||||
}
|
||||
@@ -1,26 +1,40 @@
|
||||
import { prisma } from "@/module/_global";
|
||||
import { funGetUserByCookies } from "@/module/auth";
|
||||
import _ from "lodash";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export default async function createDivision(req: Request) {
|
||||
try {
|
||||
const data = await req.json();
|
||||
const insert = await prisma.division.create({
|
||||
const sent = await req.json();
|
||||
const user = await funGetUserByCookies();
|
||||
|
||||
const insertDivision = await prisma.division.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
idVillage: data.idVillage,
|
||||
idGroup: data.idGroup,
|
||||
desc: data.desc,
|
||||
createdBy: data.createdBy
|
||||
name: sent.data.name,
|
||||
idVillage: String(user.idVillage),
|
||||
idGroup: sent.data.idGroup,
|
||||
desc: sent.data.desc,
|
||||
createdBy: String(user.id)
|
||||
},
|
||||
select: {
|
||||
id: true
|
||||
}
|
||||
})
|
||||
|
||||
const dataMember = sent.member.map((v: any) => ({
|
||||
..._.omit(v, ["isActive", "nik", "name", "phone", "email", "gender", "group", "position"]),
|
||||
idUser: v.id,
|
||||
idDivision: insertDivision.id,
|
||||
isAdmin: sent.admin.some((i: any) => i == v.id)
|
||||
}))
|
||||
|
||||
const insertMember = await prisma.divisionMember.createMany({
|
||||
data: data.member
|
||||
data: dataMember
|
||||
})
|
||||
|
||||
return Response.json(insert, { status: 201 });
|
||||
revalidatePath("/division");
|
||||
|
||||
return Response.json({ success: true, message: "Sukses menambahkan data divisi" }, { status: 201 });
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
||||
@@ -3,7 +3,7 @@ import NavbarAdminDivision from './ui/navbar_admin_division';
|
||||
|
||||
export default function CreateAdminDivision({ data }: { data: any }) {
|
||||
return (
|
||||
<NavbarAdminDivision />
|
||||
<NavbarAdminDivision data={data} onSuccess={() => { }} />
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import { funGetUserByCookies } from "@/module/auth";
|
||||
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";
|
||||
|
||||
|
||||
export default function CreateDivision() {
|
||||
@@ -74,12 +75,30 @@ export default function CreateDivision() {
|
||||
}
|
||||
|
||||
|
||||
function onChooseGroup(val: any) {
|
||||
member.set([])
|
||||
setBody({ ...body, idGroup: val })
|
||||
}
|
||||
|
||||
|
||||
|
||||
useShallowEffect(() => {
|
||||
loadData();
|
||||
}, []);
|
||||
|
||||
if (isChooseAdmin) return <CreateAdminDivision data={body} />
|
||||
if (isChooseAdmin) return <NavbarAdminDivision data={body} onSuccess={(val) => {
|
||||
if (val) {
|
||||
member.set([])
|
||||
setBody({
|
||||
...body,
|
||||
idGroup: "",
|
||||
name: "",
|
||||
desc: "",
|
||||
})
|
||||
}
|
||||
|
||||
setChooseAdmin(false)
|
||||
}} />
|
||||
|
||||
if (isChooseAnggota) return <NavbarCreateUsers grup={body.idGroup} onClose={() => { setChooseAnggota(false) }} />
|
||||
|
||||
@@ -101,8 +120,10 @@ export default function CreateDivision() {
|
||||
label: pro.name
|
||||
}))}
|
||||
onChange={(val) => {
|
||||
setBody({ ...body, idGroup: val })
|
||||
onChooseGroup(val)
|
||||
}}
|
||||
|
||||
value={body.idGroup}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -112,9 +133,10 @@ export default function CreateDivision() {
|
||||
size="md"
|
||||
required
|
||||
radius={40}
|
||||
value={body.name}
|
||||
onChange={(val) => { setBody({ ...body, name: val.target.value }) }}
|
||||
/>
|
||||
<Textarea size="md" placeholder="Deskripsi" label="Deskripsi" radius={10} onChange={(val) => { setBody({ ...body, desc: val }) }} />
|
||||
<Textarea size="md" placeholder="Deskripsi" label="Deskripsi" value={body.desc} radius={10} onChange={(val) => { setBody({ ...body, desc: val.currentTarget.value }) }} />
|
||||
<Box onClick={() => { onToChooseAnggota() }}>
|
||||
<Group
|
||||
justify="space-between"
|
||||
@@ -124,7 +146,7 @@ export default function CreateDivision() {
|
||||
borderRadius: 10,
|
||||
}}
|
||||
>
|
||||
<Text>Tambah Anggota</Text>
|
||||
<Text>Pilih Anggota</Text>
|
||||
<IoIosArrowDropright size={25} />
|
||||
</Group>
|
||||
</Box>
|
||||
|
||||
@@ -1,48 +1,54 @@
|
||||
"use client"
|
||||
import { LayoutNavbarNew, WARNA } from '@/module/_global';
|
||||
import { API_ADDRESS, LayoutNavbarNew, WARNA } from '@/module/_global';
|
||||
import { useHookstate } from '@hookstate/core';
|
||||
import { Avatar, Box, Button, Checkbox, Divider, Flex, Group, Stack, Text, TextInput } from '@mantine/core';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { HiMagnifyingGlass } from 'react-icons/hi2';
|
||||
import { globalMemberDivision } from '../../lib/val_division';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
const dataUser = [
|
||||
{
|
||||
id: 1,
|
||||
img: "https://i.pravatar.cc/1000?img=3",
|
||||
name: "Doni Setiawan",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
img: "https://i.pravatar.cc/1000?img=10",
|
||||
name: "Ilham Udin",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
img: "https://i.pravatar.cc/1000?img=11",
|
||||
name: "Didin Anang",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
img: "https://i.pravatar.cc/1000?img=21",
|
||||
name: "Angga Saputra",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
img: "https://i.pravatar.cc/1000?img=32",
|
||||
name: "Marcel Widianto",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
img: "https://i.pravatar.cc/1000?img=37",
|
||||
name: "Bagas Nusantara",
|
||||
},
|
||||
];
|
||||
|
||||
export default function NavbarAdminDivision() {
|
||||
export default function NavbarAdminDivision({ data, onSuccess }: { data: any, onSuccess: (val: any) => void }) {
|
||||
const router = useRouter()
|
||||
const member = useHookstate(globalMemberDivision)
|
||||
const [value, setValue] = useState<string[]>([]);
|
||||
|
||||
async function onSubmit() {
|
||||
if (value.length === 0) {
|
||||
return toast.error("Error! Silahkan pilih admin divisi")
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await fetch(API_ADDRESS.apiCreateDivision, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
data: data,
|
||||
member: member.get(),
|
||||
admin: value
|
||||
})
|
||||
})
|
||||
|
||||
const errorData = await res.json();
|
||||
|
||||
if (res.status == 201) {
|
||||
toast.success('Sukses! data tersimpan')
|
||||
onSuccess(true)
|
||||
} else {
|
||||
toast.error(errorData.message);
|
||||
onSuccess(false)
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('Error')
|
||||
onSuccess(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<LayoutNavbarNew back="/division/create" title="Pilih Anggota" menu />
|
||||
<LayoutNavbarNew title="Pilih Admin Divisi" menu />
|
||||
<Box p={20}>
|
||||
<TextInput
|
||||
styles={{
|
||||
@@ -58,27 +64,33 @@ export default function NavbarAdminDivision() {
|
||||
placeholder="Pencarian"
|
||||
/>
|
||||
<Box pt={20}>
|
||||
{dataUser.map((v, i) => {
|
||||
return (
|
||||
<Box key={i}>
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
align={"center"}
|
||||
>
|
||||
<Group>
|
||||
<Avatar src={v.img} alt="it's me" size="lg" />
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||
{v.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
<Checkbox />
|
||||
</Flex>
|
||||
<Divider my={20} />
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
<Checkbox.Group value={value} onChange={setValue}>
|
||||
{
|
||||
(member.length === 0) ? (
|
||||
<Text c="dimmed" ta={"center"} fs={"italic"}>Belum ada anggota</Text>
|
||||
) : member.get().map((v: any, i: any) => {
|
||||
return (
|
||||
<Box key={i}>
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
align={"center"}
|
||||
>
|
||||
<Group>
|
||||
<Avatar src={v.img} alt="it's me" size="lg" />
|
||||
<Box>
|
||||
<Text c={WARNA.biruTua} fw={"bold"}>
|
||||
{v.name}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
<Checkbox value={v.id} />
|
||||
</Flex>
|
||||
<Divider my={20} />
|
||||
</Box>
|
||||
);
|
||||
})
|
||||
}
|
||||
</Checkbox.Group>
|
||||
</Box>
|
||||
<Box mt="xl">
|
||||
<Button
|
||||
@@ -87,7 +99,7 @@ export default function NavbarAdminDivision() {
|
||||
size="lg"
|
||||
radius={30}
|
||||
fullWidth
|
||||
onClick={() => router.push("/division")}
|
||||
onClick={() => { onSubmit() }}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { HiMagnifyingGlass } from 'react-icons/hi2';
|
||||
import { globalMemberDivision } from '../../lib/val_division';
|
||||
import { TypeUser } from '@/module/user';
|
||||
import { funGetUserByCookies } from '@/module/auth';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
const dataUser = [
|
||||
{
|
||||
@@ -46,22 +47,38 @@ const dataUser = [
|
||||
|
||||
export default function NavbarCreateUsers({ grup, onClose }: { grup?: string, onClose: (val: any) => void }) {
|
||||
const router = useRouter()
|
||||
const [selectedFiles, setSelectedFiles] = useState<Record<number, boolean>>({});
|
||||
const member = useHookstate(globalMemberDivision)
|
||||
const [selectedFiles, setSelectedFiles] = useState<any>([]);
|
||||
const [dataMember, setDataMember] = useState<TypeUser>([])
|
||||
|
||||
const handleFileClick = (index: number) => {
|
||||
setSelectedFiles((prevSelectedFiles) => ({
|
||||
...prevSelectedFiles,
|
||||
[index]: !prevSelectedFiles[index],
|
||||
}));
|
||||
if (selectedFiles.some((i: any) => i.id == dataMember[index].id)) {
|
||||
setSelectedFiles(selectedFiles.filter((i: any) => i.id != dataMember[index].id))
|
||||
} else {
|
||||
setSelectedFiles([...selectedFiles, dataMember[index]])
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
async function loadData() {
|
||||
const loadMember = await fetch(API_ADDRESS.apiGetAllUser + '&active=true&groupID=' + grup);
|
||||
const user = await funGetUserByCookies();
|
||||
const hasil = await loadMember.json()
|
||||
setDataMember(hasil.filter((i: any) => i.id != user.id))
|
||||
|
||||
// cek data member sebelumnya
|
||||
if (member.length > 0) {
|
||||
setSelectedFiles(JSON.parse(JSON.stringify(member.get())))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onSubmit() {
|
||||
if (selectedFiles.length == 0) {
|
||||
return toast.error("Error! silahkan pilih anggota")
|
||||
}
|
||||
member.set(selectedFiles)
|
||||
onClose(true)
|
||||
}
|
||||
|
||||
useShallowEffect(() => {
|
||||
@@ -93,7 +110,7 @@ export default function NavbarCreateUsers({ grup, onClose }: { grup?: string, on
|
||||
verticalSpacing={{ base: "md", sm: "xl" }}
|
||||
>
|
||||
{dataMember.map((v, index) => {
|
||||
const isSelected = selectedFiles[index];
|
||||
const isSelected = selectedFiles.some((i: any) => i.id == dataMember[index].id);
|
||||
return (
|
||||
<Box key={index} mb={10}>
|
||||
<Box
|
||||
@@ -125,7 +142,7 @@ export default function NavbarCreateUsers({ grup, onClose }: { grup?: string, on
|
||||
size="lg"
|
||||
radius={30}
|
||||
fullWidth
|
||||
onClick={() => { onClose(true) }}
|
||||
onClick={() => { onSubmit() }}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user