feat : api

Deskripsi:
- add group
- add position

No issue
This commit is contained in:
lukman
2024-07-30 17:45:02 +08:00
parent 2e8d2b3c1f
commit 01016bede9
12 changed files with 214 additions and 224 deletions

View File

@@ -26,4 +26,14 @@ export const API_ADDRESS = {
"apiCreateVillage": "/api/village/post?path=create-village",
"apiUpdateVillage": "/api/village/post?path=update-village",
"apiDeleteVillage": "/api/village/post?path=delete-village",
// Position
"apiGetAllPosition": "/api/position/get?path=get-all-position",
"apiGetOnePosition": "/api/position/get?path=get-one-position",
"apiCreatePosition": "/api/position/post?path=create-position",
"apiUpdatePosition": "/api/position/post?path=update-position",
"apiDeletePosition": "/api/position/post?path=delete-position",
}

View File

@@ -0,0 +1,33 @@
import { ActionIcon, Box, Group, Skeleton } from '@mantine/core';
import React from 'react';
export default function SkeletonSingle() {
return (
<Box pt={20}>
<Group
align="center"
style={{
border: `1px solid ${"#DCEED8"}`,
padding: 10,
borderRadius: 10,
cursor: "pointer",
}}
>
<Box>
<ActionIcon
variant="light"
bg={"#DCEED8"}
size={50}
radius={100}
aria-label="icon"
>
<Skeleton height={25} width={25} />
</ActionIcon>
</Box>
<Box>
<Skeleton height={20} width={100} />
</Box>
</Group>
</Box>
);
}

View File

@@ -1,6 +1,7 @@
import { API_ADDRESS } from "./bin/api_address";
import prisma from "./bin/prisma";
import { pwd_key_config } from "./bin/val_global";
import SkeletonSingle from "./components/skeleton_single";
import { WARNA } from "./fun/WARNA";
import LayoutDrawer from "./layout/layout_drawer";
import LayoutIconBack from "./layout/layout_icon_back";
@@ -20,4 +21,5 @@ export { LayoutNavbarNew };
export { ViewFilter };
export { prisma };
export { pwd_key_config };
export { API_ADDRESS };
export { API_ADDRESS };
export {SkeletonSingle}

View File

@@ -44,6 +44,8 @@ export default function ViewVerification({ phone, otp, user }: IVerification) {
toast.error(setCookies.message)
}
setLoading(false)
} else {

View File

@@ -1,4 +1,4 @@
import { API_ADDRESS, LayoutDrawer, WARNA } from "@/module/_global";
import { API_ADDRESS, LayoutDrawer, SkeletonSingle, WARNA } from "@/module/_global";
import {
ActionIcon,
Box,
@@ -74,32 +74,9 @@ export default function ListGroupActive({ status }: { status: boolean }) {
? Array(6)
.fill(null)
.map((_, i) => (
<Box pt={20} key={i}>
<Group
align="center"
style={{
border: `1px solid ${"#DCEED8"}`,
padding: 10,
borderRadius: 10,
cursor: "pointer",
}}
>
<Box>
<ActionIcon
variant="light"
bg={"#DCEED8"}
size={50}
radius={100}
aria-label="icon"
>
<Skeleton height={25} width={25} />
</ActionIcon>
</Box>
<Box>
<Skeleton height={20} width={100} />
</Box>
</Group>
</Box>
<Box key={i}>
<SkeletonSingle />
</Box>
))
: isData.map((v, i) => {
return (

View File

@@ -41,11 +41,11 @@ export default function EditDrawerGroup({
},
body: JSON.stringify({
id: id,
name : name
name: name
}),
});
setOpenDrawerGroup(false);
onUpdated(true);
onUpdated(true);
} catch (error) {
console.error(error);
}

View File

@@ -1,22 +1,35 @@
import { prisma } from "@/module/_global";
import _, { omit } from "lodash";
import { NextRequest } from "next/server";
export async function getAllPosition(req: NextRequest) {
try {
const searchParams = req.nextUrl.searchParams
const groupID = searchParams.get('groupID');
const groupID = "3";
const active = searchParams.get('active');
const positions = await prisma.position.findMany({
where: {
idGroup: String(groupID),
isActive: true,
isActive: (active == "true" ? true : false),
},
select: {
id: true,
name: true,
isActive: true,
Group: {
select: {
name: true
}
}
},
});
return Response.json(positions);
const allData = positions.map((v: any) => ({
..._.omit(v, ["Group"]),
group: v.Group.name
}))
return Response.json(allData);
} catch (error) {
console.error(error);
return Response.json({ success: false, message: "Internal Server Error" }, { status: 500 });

View File

@@ -1,18 +1,21 @@
import { prisma } from "@/module/_global";
import { revalidatePath } from "next/cache";
export async function deletePosition(req: Request) {
try {
const data = await req.json();
const active = data.isActive;
const update = await prisma.position.update({
where: {
id: data.id,
},
data: {
isActive: false,
isActive: !active,
},
});
revalidatePath("/position");
return Response.json(
{ success: true, message: "Sukses Delete Position" },
{ status: 200 }

View File

@@ -3,7 +3,6 @@ import { Box, Tabs, rem } from '@mantine/core';
import { IoCloseCircleOutline } from "react-icons/io5"
import { IoMdCheckmarkCircleOutline } from "react-icons/io"
import ListPositionActive from './ui/list_position_active';
import ListPositionNonActive from './ui/list_position_nonactive';
export default function TabListGroup() {
const iconStyle = { width: rem(20), height: rem(20) };
@@ -25,11 +24,12 @@ export default function TabListGroup() {
</Tabs.List>
<Tabs.Panel value="aktif">
<ListPositionActive />
<ListPositionActive status={true} />
</Tabs.Panel>
<Tabs.Panel value="tidak-aktif">
<ListPositionNonActive />
<ListPositionActive status={false} />
{/* <ListPositionNonActive /> */}
</Tabs.Panel>
</Tabs>
</Box>

View File

@@ -1,10 +1,14 @@
import { LayoutDrawer, WARNA } from "@/module/_global"
import { API_ADDRESS, LayoutDrawer, WARNA } from "@/module/_global"
import LayoutModal from "@/module/_global/layout/layout_modal"
import { Box, Stack, SimpleGrid, Flex, Text, Select, TextInput, Button } from "@mantine/core"
import { useState } from "react"
import toast from "react-hot-toast"
import { FaPencil, FaToggleOff } from "react-icons/fa6"
export default function DrawerDetailPosition({ onUpdated }: { onUpdated: (val: boolean) => void }) {
export default function DrawerDetailPosition({ onUpdated, id, isActive, }: {
onUpdated: (val: boolean) => void, id: string | null,
isActive: boolean | null;
}) {
const [openDrawerGroup, setOpenDrawerGroup] = useState(false)
const [isModal, setModal] = useState(false)
@@ -20,6 +24,36 @@ export default function DrawerDetailPosition({ onUpdated }: { onUpdated: (val: b
setModal(false)
}
async function nonActive(val: boolean) {
try {
if (val) {
const res = await fetch(API_ADDRESS.apiDeletePosition, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
id,
isActive,
}),
});
if (res.status == 200) {
onUpdated(true);
} else {
onUpdated(false);
}
}
setModal(false);
} catch (error) {
console.log(error);
setModal(false);
toast.error("Terjadi kesalahan");
onUpdated(false);
}
}
return (
<Box>
<Stack pt={10}>
@@ -102,7 +136,7 @@ export default function DrawerDetailPosition({ onUpdated }: { onUpdated: (val: b
<LayoutModal opened={isModal} onClose={() => setModal(false)}
description="Apakah Anda yakin ingin mengubah status aktifasi data?"
onYes={(val) => { onTrue(val) }} />
onYes={(val) => { nonActive(val) }} />
</Box>
)
}

View File

@@ -1,57 +1,46 @@
import { LayoutDrawer, WARNA } from '@/module/_global';
import { ActionIcon, Box, Group, Text, TextInput } from '@mantine/core';
import React, { useState } from 'react';
import { FaUserTie } from 'react-icons/fa6';
import { HiMagnifyingGlass } from 'react-icons/hi2';
import DrawerDetailPosition from './drawer_detail_position';
import toast from 'react-hot-toast';
import { API_ADDRESS, LayoutDrawer, SkeletonSingle, WARNA } from "@/module/_global";
import { ActionIcon, Box, Group, Text, TextInput } from "@mantine/core";
import React, { useEffect, useState } from "react";
import { FaUserTie } from "react-icons/fa6";
import { HiMagnifyingGlass } from "react-icons/hi2";
import DrawerDetailPosition from "./drawer_detail_position";
import toast from "react-hot-toast";
import _ from "lodash";
const dataGroup = [
{
id: 1,
name: 'Kepala',
grup: 'Dinas'
},
{
id: 2,
name: 'Sekretaris',
grup: 'LPD'
},
{
id: 3,
name: 'Bendahara',
grup: 'Dinas'
},
{
id: 4,
name: 'Anggota',
grup: 'Karang Taruna'
},
{
id: 5,
name: 'Kepala Urusan Kemasyarakatan',
grup: 'Dinas'
},
{
id: 6,
name: 'Kepala Urusan Pemerintahan',
grup: 'Dinas'
},
{
id: 7,
name: 'Kepala Urusan Kependudukan',
grup: 'Dinas'
},
{
id: 8,
name: 'Anggota',
grup: 'Dinas'
},
]
type dataPosition = {
name: string;
idGroup: string;
group: string;
id: string;
isActive: boolean
};
export default function ListPositionActive() {
const [openDrawer, setOpenDrawer] = useState(false)
const [isData, setData] = useState("")
export default function ListPositionActive({ status }: { status: boolean }) {
const [openDrawer, setOpenDrawer] = useState(false);
const [isData, setData] = useState("");
const [isDataPosition, setDataPosition] = useState<dataPosition[]>([]);
const [loading, setLoading] = useState(true);
const [selectId, setSelectId] = useState<string | null>(null);
const [active, setActive] = useState<boolean | null>(null)
async function getAllPosition() {
try {
setDataPosition([]);
setLoading(true)
const res = await fetch(`${API_ADDRESS.apiGetAllPosition}&active=` + status);
const data = await res.json();
setDataPosition(data);
setLoading(false);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
useEffect(() => {
getAllPosition();
}, [status])
return (
<Box pt={20}>
@@ -68,35 +57,65 @@ export default function ListPositionActive() {
leftSection={<HiMagnifyingGlass size={20} />}
placeholder="Pencarian"
/>
{dataGroup.map((v, i) => {
return (
<Box pt={20} key={i}>
<Group align='center' style={{
border: `1px solid ${"#DCEED8"}`,
padding: 10,
borderRadius: 10
}} onClick={() => {
setData(v.name)
setOpenDrawer(true)
}} >
<Box>
<ActionIcon variant="light" bg={'#DCEED8'} size={50} radius={100} aria-label="icon">
<FaUserTie color={WARNA.biruTua} size={25} />
</ActionIcon>
</Box>
<Box>
<Text fw={'bold'} c={WARNA.biruTua}>{v.name}</Text>
<Text fw={'lighter'} fz={12}>{v.grup}</Text>
</Box>
</Group>
</Box>
)
})}
<LayoutDrawer opened={openDrawer} onClose={() => setOpenDrawer(false)} title={isData}>
<DrawerDetailPosition onUpdated={() => {
setOpenDrawer(false)
toast.success('Sukses! data tersimpan')
}} />
{loading ? Array(6).fill(null).map((_, i) => (
<Box key={i}>
<SkeletonSingle />
</Box>
)) :
isDataPosition.map((v, i) => {
return (
<Box pt={20} key={i}>
<Group
align="center"
style={{
border: `1px solid ${"#DCEED8"}`,
padding: 10,
borderRadius: 10,
}}
onClick={() => {
setData(v.name);
setOpenDrawer(true);
setSelectId(v.id);
setActive(v.isActive);
}}
>
<Box>
<ActionIcon
variant="light"
bg={"#DCEED8"}
size={50}
radius={100}
aria-label="icon"
>
<FaUserTie color={WARNA.biruTua} size={25} />
</ActionIcon>
</Box>
<Box>
<Text fw={"bold"} c={WARNA.biruTua}>
{v.name}
</Text>
<Text fw={"lighter"} fz={12}>
{v.group}
</Text>
</Box>
</Group>
</Box>
);
})
}
<LayoutDrawer
opened={openDrawer}
onClose={() => setOpenDrawer(false)}
title={isData}
>
<DrawerDetailPosition
id={selectId}
isActive={active}
onUpdated={() => {
setOpenDrawer(false);
toast.success("Sukses! data tersimpan");
}}
/>
</LayoutDrawer>
</Box>
);

View File

@@ -1,103 +0,0 @@
import { LayoutDrawer, WARNA } from '@/module/_global';
import { ActionIcon, Box, Group, Text, TextInput } from '@mantine/core';
import React, { useState } from 'react';
import { FaUserTie } from 'react-icons/fa6';
import { HiMagnifyingGlass } from 'react-icons/hi2';
import DrawerDetailPosition from './drawer_detail_position';
import toast from 'react-hot-toast';
const dataGroup = [
{
id: 1,
name: 'Kepala',
grup: 'Dinas'
},
{
id: 2,
name: 'Sekretaris',
grup: 'LPD'
},
{
id: 3,
name: 'Bendahara',
grup: 'Dinas'
},
{
id: 4,
name: 'Anggota',
grup: 'Karang Taruna'
},
{
id: 5,
name: 'Kepala Urusan Kemasyarakatan',
grup: 'Dinas'
},
{
id: 6,
name: 'Kepala Urusan Pemerintahan',
grup: 'Dinas'
},
{
id: 7,
name: 'Kepala Urusan Kependudukan',
grup: 'Dinas'
},
{
id: 8,
name: 'Anggota',
grup: 'Dinas'
},
]
export default function ListPositionNonActive() {
const [openDrawer, setOpenDrawer] = useState(false)
const [isData, setData] = useState("")
return (
<Box pt={20}>
<TextInput
styles={{
input: {
color: WARNA.biruTua,
borderRadius: WARNA.biruTua,
borderColor: WARNA.biruTua,
},
}}
size="md"
radius={30}
leftSection={<HiMagnifyingGlass size={20} />}
placeholder="Pencarian"
/>
{dataGroup.map((v, i) => {
return (
<Box pt={20} key={i}>
<Group align='center' style={{
border: `1px solid ${"#DCEED8"}`,
padding: 10,
borderRadius: 10
}} onClick={() => {
setData(v.name)
setOpenDrawer(true)
}}>
<Box>
<ActionIcon variant="light" bg={'#DCEED8'} size={50} radius={100} aria-label="icon">
<FaUserTie color={WARNA.biruTua} size={25} />
</ActionIcon>
</Box>
<Box>
<Text fw={'bold'} c={WARNA.biruTua}>{v.name}</Text>
<Text fw={'lighter'} fz={12}>{v.grup}</Text>
</Box>
</Group>
</Box>
)
})}
<LayoutDrawer opened={openDrawer} onClose={() => setOpenDrawer(false)} title={isData}>
<DrawerDetailPosition onUpdated={() => {
setOpenDrawer(false)
toast.success('Sukses! data tersimpan')
}} />
</LayoutDrawer>
</Box>
);
}