diff --git a/src/app/(application)/announcement/create-user/page.tsx b/src/app/(application)/announcement/create-user/page.tsx index 74e004b..32d717c 100644 --- a/src/app/(application)/announcement/create-user/page.tsx +++ b/src/app/(application)/announcement/create-user/page.tsx @@ -1,4 +1,4 @@ -import CreateUsersAnnouncement from '@/module/announcement/component/create_users_announcement'; +import CreateUsersAnnouncement from '@/module/announcement/ui/create_users_announcement'; import React from 'react'; function Page() { diff --git a/src/app/(application)/announcement/create/page.tsx b/src/app/(application)/announcement/create/page.tsx index c4f77f1..7e09362 100644 --- a/src/app/(application)/announcement/create/page.tsx +++ b/src/app/(application)/announcement/create/page.tsx @@ -1,8 +1,9 @@ -import { ViewCreateAnnouncement } from "@/module/announcement"; + function Page() { return ( - + "" + // ) } diff --git a/src/app/(application)/announcement/edit/[id]/page.tsx b/src/app/(application)/announcement/edit/[id]/page.tsx index b9f348b..11a0820 100644 --- a/src/app/(application)/announcement/edit/[id]/page.tsx +++ b/src/app/(application)/announcement/edit/[id]/page.tsx @@ -1,8 +1,9 @@ -import { ViewEditAnnouncement } from "@/module/announcement"; +// import { ViewEditAnnouncement } from "@/module/announcement"; function Page({ params }: { params: { id: any } }) { return ( - + // + "" ) } diff --git a/src/app/(application)/announcement/page.tsx b/src/app/(application)/announcement/page.tsx index ba6abbb..25b2f51 100644 --- a/src/app/(application)/announcement/page.tsx +++ b/src/app/(application)/announcement/page.tsx @@ -1,11 +1,15 @@ import { ViewFilter } from "@/module/_global"; -import { ViewListAnnouncement } from "@/module/announcement"; +import { ListAnnouncement, NavbarAnnouncement } from "@/module/announcement"; +import { Box } from "@mantine/core"; function Page({ searchParams }: { searchParams: { page: string } }) { if (searchParams.page == 'filter') - return + return return ( - + + + + ) } diff --git a/src/app/(application)/position/page.tsx b/src/app/(application)/position/page.tsx index fc42b06..d9fcb85 100644 --- a/src/app/(application)/position/page.tsx +++ b/src/app/(application)/position/page.tsx @@ -1,13 +1,17 @@ import { ViewFilter } from '@/module/_global'; -import { ViewListPosition } from '@/module/position'; +import { NavbarListPosition, TabListPosition } from '@/module/position'; +import { Box } from '@mantine/core'; import React from 'react'; function Page({ searchParams }: { searchParams: { page: string } }) { if (searchParams.page == "filter") - return + return return ( - + + + + ); } diff --git a/src/app/api/announcement/[id]/route.ts b/src/app/api/announcement/[id]/route.ts new file mode 100644 index 0000000..6f86b70 --- /dev/null +++ b/src/app/api/announcement/[id]/route.ts @@ -0,0 +1,58 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import _ from "lodash"; +import { NextResponse } from "next/server"; + +export async function GET(request: Request, context: { params: { id: string } }) { + try { + const { id } = context.params; + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + const { searchParams } = new URL(request.url); + // const announcementId = searchParams.get("announcement"); + const announcement = await prisma.announcement.findUnique({ + where: { + id: id, + }, + select: { + id: true, + title: true, + desc: true, + }, + }); + const announcementMember = await prisma.announcementMember.findMany({ + where: { + idAnnouncement: id, + }, + select: { + idAnnouncement: true, + idGroup: true, + idDivision: true, + Group: { + select: { + name: true, + }, + }, + }, + }); + + const allAnnouncementMember = announcementMember.map((v: any) => ({ + ..._.omit(v, ["Group"]), + group: v.Group.name, + })) + + return NextResponse.json( + { + success: true, + message: "Berhasil mendapatkan announcement", + announcement, allAnnouncementMember + }, + { status: 200 } + ); + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan announcement, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/announcement/route.ts b/src/app/api/announcement/route.ts new file mode 100644 index 0000000..327a073 --- /dev/null +++ b/src/app/api/announcement/route.ts @@ -0,0 +1,46 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import _ from "lodash"; +import moment from "moment"; +import "moment/locale/id"; +import { NextResponse } from "next/server"; + +export const dynamic = 'force-dynamic' +export async function GET(request: Request) { + try { + const user = await funGetUserByCookies(); + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + + const villageId = user.idVillage + const { searchParams } = new URL(request.url); + const name = searchParams.get('search'); + const announcements = await prisma.announcement.findMany({ + where: { + idVillage: String(villageId), + isActive: true, + title: { + contains: (name == undefined || name == null) ? "" : name, + mode: "insensitive" + } + }, + select: { + id: true, + title: true, + desc: true, + createdAt: true, + }, + }); + + const allData = announcements.map((v: any) => ({ + ..._.omit(v, ["createdAt"]), + createdAt: moment(v.createdAt).format("LL") + })) + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan pengumuman", data: allData, }, { status: 200 }); + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan pengumuman, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} diff --git a/src/app/api/position/[id]/route.ts b/src/app/api/position/[id]/route.ts new file mode 100644 index 0000000..ae15c91 --- /dev/null +++ b/src/app/api/position/[id]/route.ts @@ -0,0 +1,131 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import { revalidatePath } from "next/cache"; +import { NextResponse } from "next/server"; + +// GET ONE JABATAN +export async function GET(request: Request, context: { params: { id: string } }) { + try { + const { id } = context.params; + 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 prisma.position.findUnique({ + where: { + id: id, + }, + select: { + id: true, + name: true, + idGroup: true, + }, + }); + if (!data) { + return NextResponse.json( + { + success: false, + message: "Gagal mendapatkan jabatan, data tidak ditemukan", + }, + { status: 404 } + ); + } + + return NextResponse.json( + { + success: true, + message: "Berhasil mendapatkan jabatan", + data, + }, + { 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 }); + } +} + +// DELETE / ACTIVE & NON ACTIVE POSITION +export async function DELETE(request: Request, context: { params: { id: string } }) { + try { + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + const { id } = context.params; + const { isActive } = (await request.json()); + const data = await prisma.position.count({ + where: { + id: id, + }, + }); + + if (data == 0) { + return NextResponse.json( + { + success: false, + message: "Gagal delete jabatan, data tidak ditemukan", + }, + { status: 404 } + ); + } + + + const update = await prisma.position.update({ + where: { + id: id, + }, + data: { + isActive: !isActive, + }, + }); + + return NextResponse.json( + { success: true, message: "Sukses Delete Position" }, + { status: 200 } + ); + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan position, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} + + +// UPDATE POSITION +export async function PUT(request: Request, context: { params: { id: string } }) { + try { + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + const { id } = context.params; + const data = await request.json(); + const cek = await prisma.position.count({ + where: { + name: data.name, + idGroup: data.idGroup, + }, + }); + if (cek == 0) { + const positions = await prisma.position.update({ + where: { + id: id, + }, + data: { + name: data.name, + idGroup: data.idGroup, + }, + }); + return NextResponse.json({ success: true, message: "Berhasil edit position", positions, }, { status: 200 }); + } else { + return NextResponse.json( + { success: false, message: "Position sudah ada" }, + { status: 400 } + ); + } + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal mendapatkan jabatan, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/position/route.ts b/src/app/api/position/route.ts new file mode 100644 index 0000000..ade9980 --- /dev/null +++ b/src/app/api/position/route.ts @@ -0,0 +1,106 @@ +import { prisma } from "@/module/_global"; +import { funGetUserByCookies } from "@/module/auth"; +import _ from "lodash"; +import { revalidatePath, revalidateTag } from "next/cache"; +import { NextResponse } from "next/server"; + + +// GET ALL POSITION +export async function GET(request: Request) { + try { + + let grupFix + const { searchParams } = new URL(request.url); + const groupID = searchParams.get('group'); + const active = searchParams.get('active'); + const name = searchParams.get('search') + const user = await funGetUserByCookies() + if (user.id == undefined) { + return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 }); + } + + if (groupID == "null") { + grupFix = user.idGroup + } else { + grupFix = groupID + } + + const positions = await prisma.position.findMany({ + where: { + idGroup: String(grupFix), + isActive: (active == "true" ? true : false), + name: { + contains: (name == undefined || name == null) ? "" : name, + mode: "insensitive" + } + }, + select: { + id: true, + name: true, + isActive: true, + Group: { + select: { + name: true + } + } + }, + }); + + const allData = positions.map((v: any) => ({ + ..._.omit(v, ["Group"]), + group: v.Group.name + })) + + return NextResponse.json({ success: true, message: "Berhasil mendapatkan jabatan", data: allData, }, { 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 }); + } +} + + + +// CREATE POSITION +export async function POST(request: Request) { + 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 cek = await prisma.position.count({ + where: { + name: data.name, + idGroup: data.idGroup, + }, + }); + if (cek == 0) { + const positions = await prisma.position.create({ + data: { + name: data.name, + idGroup: data.idGroup, + }, + select: { + id: true, + name: true, + }, + }); + + revalidatePath('/api/position?active=true', "page") + revalidatePath('/api/position?active=false', 'page') + revalidatePath('/position?active=true', 'page') + revalidateTag('position') + + return NextResponse.json({ success: true, message: "Berhasil menambahkan position", positions, }, { status: 200 }); + } else { + return NextResponse.json( + { success: false, message: "Position sudah ada" }, + { status: 400 } + ); + } + + } catch (error) { + console.error(error); + return NextResponse.json({ success: false, message: "Gagal menambahkan position, coba lagi nanti", reason: (error as Error).message, }, { status: 500 }); + } +} diff --git a/src/module/announcement/index.ts b/src/module/announcement/index.ts index 63e211d..dd0ec6c 100644 --- a/src/module/announcement/index.ts +++ b/src/module/announcement/index.ts @@ -1,11 +1,10 @@ import { apiAnnouncement } from "./api/api_announcement"; -import ViewCreateAnnouncement from "./view/view_create_announcement"; -import ViewDetailAnnouncement from "./view/view_detail_anouncement"; -import ViewEditAnnouncement from "./view/view_edit_announcement"; -import ViewListAnnouncement from "./view/view_list_announcement"; +import ListAnnouncement from "./ui/list_announcement"; +import NavbarAnnouncement from "./ui/navbar_announcement"; +import ViewDetailAnnouncement from "./ui/view_detail_anouncement" + -export { ViewListAnnouncement }; -export { ViewCreateAnnouncement }; export { ViewDetailAnnouncement }; -export { ViewEditAnnouncement }; export { apiAnnouncement }; +export { ListAnnouncement } +export { NavbarAnnouncement } \ No newline at end of file diff --git a/src/module/announcement/lib/api_announcement.ts b/src/module/announcement/lib/api_announcement.ts new file mode 100644 index 0000000..1d65d43 --- /dev/null +++ b/src/module/announcement/lib/api_announcement.ts @@ -0,0 +1,9 @@ +export const funGetAllAnnouncement = async (path?: string) => { + const response = await fetch(`/api/announcement${(path) ? path : ''}`, { next: { tags: ['announcement'] } }); + return await response.json().catch(() => null); +} + +export const funGetAnnouncementById = async (path: string) => { + const response = await fetch(`/api/announcement/${path}`); + return await response.json().catch(() => null); +} \ No newline at end of file diff --git a/src/module/announcement/lib/type_announcement.ts b/src/module/announcement/lib/type_announcement.ts new file mode 100644 index 0000000..4e94996 --- /dev/null +++ b/src/module/announcement/lib/type_announcement.ts @@ -0,0 +1,24 @@ +export interface IListDataAnnouncement { + id: string, + title: string, + desc: string, + createdAt: string +} + +export interface IRootAllAnnouncement { + announcement: IAnnouncement + allAnnouncementMember: IAllAnnouncementMember[] + } + + export interface IAnnouncement { + id: string + title: string + desc: string + } + + export interface IAllAnnouncementMember { + idAnnouncement: string + idGroup: string + idDivision: string + group: string + } \ No newline at end of file diff --git a/src/module/announcement/component/create_announcement.tsx b/src/module/announcement/ui/create_announcement.tsx similarity index 95% rename from src/module/announcement/component/create_announcement.tsx rename to src/module/announcement/ui/create_announcement.tsx index e28c4f4..0a8e1d8 100644 --- a/src/module/announcement/component/create_announcement.tsx +++ b/src/module/announcement/ui/create_announcement.tsx @@ -1,5 +1,5 @@ 'use client' -import { WARNA } from "@/module/_global"; +import { LayoutNavbarNew, WARNA } from "@/module/_global"; import LayoutModal from "@/module/_global/layout/layout_modal"; import { Box, Button, Group, Stack, Text, Textarea, TextInput } from "@mantine/core"; import { useRouter } from "next/navigation"; @@ -21,6 +21,7 @@ export default function CreateAnnouncement() { return ( + } /> diff --git a/src/module/announcement/component/create_users_announcement.tsx b/src/module/announcement/ui/create_users_announcement.tsx similarity index 100% rename from src/module/announcement/component/create_users_announcement.tsx rename to src/module/announcement/ui/create_users_announcement.tsx diff --git a/src/module/announcement/component/detail_announcement.tsx b/src/module/announcement/ui/detail_announcement.tsx similarity index 77% rename from src/module/announcement/component/detail_announcement.tsx rename to src/module/announcement/ui/detail_announcement.tsx index f741879..2dffc49 100644 --- a/src/module/announcement/component/detail_announcement.tsx +++ b/src/module/announcement/ui/detail_announcement.tsx @@ -5,37 +5,28 @@ import { useShallowEffect } from "@mantine/hooks"; import { useState } from "react"; import { BsCardText } from "react-icons/bs"; import { TfiAnnouncement } from "react-icons/tfi"; +import { IRootAllAnnouncement } from "../lib/type_announcement"; +import { funGetAnnouncementById } from "../lib/api_announcement"; +import toast from "react-hot-toast"; -export interface RootAll { - announcement: Announcement - allAnnouncementMember: AllAnnouncementMember[] -} -export interface Announcement { - id: string - title: string - desc: string -} - -export interface AllAnnouncementMember { - idAnnouncement: string - idGroup: string - idDivision: string - group: string -} export default function DetailAnnouncement({ id }: { id: string }) { - const [isData, setIsData] = useState() + const [isData, setIsData] = useState() async function fetchOneAnnouncement() { try { - const res = await fetch(`${API_ADDRESS.apiGetOneAnnouncement}&announcementId=${id}`) - const data = await res.json() - setIsData(data) + const res = await funGetAnnouncementById(id) + if (res.success) { + setIsData(res) + } else { + toast.error(res.message) + } + } catch (error) { console.error(error) - throw new Error("Error") + toast.error("Gagal mendapatkan announcement, coba lagi nanti") } } diff --git a/src/module/announcement/component/ui/drawer_announcement.tsx b/src/module/announcement/ui/drawer_announcement.tsx similarity index 100% rename from src/module/announcement/component/ui/drawer_announcement.tsx rename to src/module/announcement/ui/drawer_announcement.tsx diff --git a/src/module/announcement/component/ui/drawer_detail_announcement.tsx b/src/module/announcement/ui/drawer_detail_announcement.tsx similarity index 100% rename from src/module/announcement/component/ui/drawer_detail_announcement.tsx rename to src/module/announcement/ui/drawer_detail_announcement.tsx diff --git a/src/module/announcement/component/edit_announcement.tsx b/src/module/announcement/ui/edit_announcement.tsx similarity index 94% rename from src/module/announcement/component/edit_announcement.tsx rename to src/module/announcement/ui/edit_announcement.tsx index 73a73c1..14eac42 100644 --- a/src/module/announcement/component/edit_announcement.tsx +++ b/src/module/announcement/ui/edit_announcement.tsx @@ -1,5 +1,5 @@ 'use client' -import { WARNA } from "@/module/_global"; +import { LayoutNavbarNew, WARNA } from "@/module/_global"; import LayoutModal from "@/module/_global/layout/layout_modal"; import { Box, Button, Stack, Textarea, TextInput } from "@mantine/core"; import { useState } from "react"; @@ -17,6 +17,7 @@ export default function EditAnnouncement() { } return ( <> + } /> ([]) + const [isData, setIsData] = useState([]) + const [searchQuery, setSearchQuery] = useState('') const router = useRouter() - async function fetchGetAllAnnouncement() { + const fetchData = async () => { try { - const res = await fetch(`${API_ADDRESS.apiGetAllAnnouncement}`) - const data = await res.json() - setIsData(data) + const response = await funGetAllAnnouncement('?search=' + searchQuery) + + if (response.success) { + setIsData(response?.data) + } else { + toast.error(response.message); + } + } catch (error) { - console.error(error) - throw new Error("Error") + toast.error("Gagal mendapatkan announcement, coba lagi nanti"); + console.error(error); } } useShallowEffect(() => { - fetchGetAllAnnouncement() - }, []) + fetchData() + }, [searchQuery]) return ( @@ -47,7 +50,8 @@ export default function ListAnnouncement() { radius={30} leftSection={} placeholder="Pencarian" - /> + onChange={(e) => setSearchQuery(e.target.value)} + /> {isData.map((v, i) => { return ( diff --git a/src/module/announcement/component/ui/navbar_announcement.tsx b/src/module/announcement/ui/navbar_announcement.tsx similarity index 100% rename from src/module/announcement/component/ui/navbar_announcement.tsx rename to src/module/announcement/ui/navbar_announcement.tsx diff --git a/src/module/announcement/component/ui/navbar_detail_announcement.tsx b/src/module/announcement/ui/navbar_detail_announcement.tsx similarity index 100% rename from src/module/announcement/component/ui/navbar_detail_announcement.tsx rename to src/module/announcement/ui/navbar_detail_announcement.tsx diff --git a/src/module/announcement/view/view_detail_anouncement.tsx b/src/module/announcement/ui/view_detail_anouncement.tsx similarity index 61% rename from src/module/announcement/view/view_detail_anouncement.tsx rename to src/module/announcement/ui/view_detail_anouncement.tsx index 356f7ee..75b0353 100644 --- a/src/module/announcement/view/view_detail_anouncement.tsx +++ b/src/module/announcement/ui/view_detail_anouncement.tsx @@ -1,6 +1,6 @@ import { Box } from "@mantine/core"; -import DetailAnnouncement from "../component/detail_announcement"; -import NavbarDetailAnnouncement from "../component/ui/navbar_detail_announcement"; +import DetailAnnouncement from "./detail_announcement"; +import NavbarDetailAnnouncement from "./navbar_detail_announcement"; export default function ViewDetailAnnouncement({ data }: { data: string }) { return ( diff --git a/src/module/announcement/view/view_create_announcement.tsx b/src/module/announcement/view/view_create_announcement.tsx deleted file mode 100644 index 3c4e803..0000000 --- a/src/module/announcement/view/view_create_announcement.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { LayoutNavbarNew, WARNA } from "@/module/_global"; -import { Box } from "@mantine/core"; -import CreateAnnouncement from "../component/create_announcement"; - -export default function ViewCreateAnnouncement() { - return ( - - } /> - - - ) -} \ No newline at end of file diff --git a/src/module/announcement/view/view_edit_announcement.tsx b/src/module/announcement/view/view_edit_announcement.tsx deleted file mode 100644 index 39e0c16..0000000 --- a/src/module/announcement/view/view_edit_announcement.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Box } from "@mantine/core"; -import { LayoutNavbarNew } from "@/module/_global"; -import EditAnnouncement from "../component/edit_announcement"; - -export default function ViewEditAnnouncement({ data }: { data: string }) { - return ( - - } /> - - - ) -} \ No newline at end of file diff --git a/src/module/announcement/view/view_list_announcement.tsx b/src/module/announcement/view/view_list_announcement.tsx deleted file mode 100644 index 4af77e6..0000000 --- a/src/module/announcement/view/view_list_announcement.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Box } from "@mantine/core"; -import NavbarAnnouncement from "../component/ui/navbar_announcement"; -import ListAnnouncement from "../component/list_announcement"; - -export default function ViewListAnnouncement() { - return ( - - - - - ) -} \ No newline at end of file diff --git a/src/module/position/component/tab_list_position.tsx b/src/module/position/component/tab_list_position.tsx deleted file mode 100644 index 661519d..0000000 --- a/src/module/position/component/tab_list_position.tsx +++ /dev/null @@ -1,38 +0,0 @@ -'use client' -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'; - -export default function TabListGroup() { - const iconStyle = { width: rem(20), height: rem(20) }; - - return ( - - - - }> - Aktif - - }> - Tidak Aktif - - - - - - - - - - {/* */} - - - - ); -} - diff --git a/src/module/position/index.ts b/src/module/position/index.ts index bf46432..521f031 100644 --- a/src/module/position/index.ts +++ b/src/module/position/index.ts @@ -1,5 +1,8 @@ import { apiPosition } from "./api/api_position"; -import ViewListPosition from "./view/view_list_position"; +import TabListPosition from "./ui/tab_list_position"; +import TabListGroup from "./ui/tab_list_position"; +import NavbarListPosition from "./ui/navbar_list_position"; -export { ViewListPosition }; export { apiPosition }; +export { NavbarListPosition } +export { TabListPosition } \ No newline at end of file diff --git a/src/module/position/lib/api_position.ts b/src/module/position/lib/api_position.ts new file mode 100644 index 0000000..f907254 --- /dev/null +++ b/src/module/position/lib/api_position.ts @@ -0,0 +1,54 @@ +import { IDataPosition, IFormPosition, IStatusPosition } from "./type_position"; + +export const funGetAllPosition = async (path?: string) => { + const response = await fetch(`/api/position${(path) ? path : ''}`, { next: { tags: ['position'] } }); + return await response.json().catch(() => null); +} + + +export const funGetOnePosition = async (path: string) => { + const response = await fetch(`/api/position/${path}`); + return await response.json().catch(() => null); +} + +export const funCreatePosition = async (data: IFormPosition) => { + if (data.name.length < 3) + return { success: false, message: 'Minimal 3 karakter' } + + const response = await fetch("/api/position", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + + +export const funEditStatusPosition = async (path: string, data: IStatusPosition) => { + + const response = await fetch(`/api/position/${path}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} + + +export const funEditPosition = async (path: string, data: IFormPosition) => { + if (data.name.length < 3) + return { success: false, message: 'Minimal 3 karakter' } + + const response = await fetch(`/api/position/${path}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + return await response.json().catch(() => null); +} \ No newline at end of file diff --git a/src/module/position/lib/type_position.ts b/src/module/position/lib/type_position.ts new file mode 100644 index 0000000..2b151a5 --- /dev/null +++ b/src/module/position/lib/type_position.ts @@ -0,0 +1,16 @@ +export interface IDataPosition { + name: string; + idGroup: string; + group: string; + id: string; + isActive: boolean +}; + +export interface IStatusPosition { + isActive: boolean +} + +export interface IFormPosition { + name: string + idGroup: string +} \ No newline at end of file diff --git a/src/module/position/component/ui/drawer_detail_position.tsx b/src/module/position/ui/drawer_detail_position.tsx similarity index 81% rename from src/module/position/component/ui/drawer_detail_position.tsx rename to src/module/position/ui/drawer_detail_position.tsx index f8331a9..355b871 100644 --- a/src/module/position/component/ui/drawer_detail_position.tsx +++ b/src/module/position/ui/drawer_detail_position.tsx @@ -6,9 +6,11 @@ import { useShallowEffect } from "@mantine/hooks" import { useEffect, useState } from "react" import toast from "react-hot-toast" import { FaPencil, FaToggleOff } from "react-icons/fa6" +import { funEditPosition, funEditStatusPosition, funGetOnePosition } from "../lib/api_position" +import { IDataPosition } from "../lib/type_position" export default function DrawerDetailPosition({ onUpdated, id, isActive }: { - onUpdated: (val: boolean) => void, id: string | null, isActive: boolean | null; + onUpdated: (val: boolean) => void, id: string, isActive: boolean; }) { const [openDrawerGroup, setOpenDrawerGroup] = useState(false) const [isModal, setModal] = useState(false) @@ -17,7 +19,7 @@ export default function DrawerDetailPosition({ onUpdated, id, isActive }: { name: "", idGroup: "" }) - const [listGroup, setListGorup] = useState([]) + const [listGroup, setListGorup] = useState([]) function onCLose() { onUpdated(true) @@ -40,41 +42,38 @@ export default function DrawerDetailPosition({ onUpdated, id, isActive }: { async function getOneData() { try { - const res = await fetch(`${API_ADDRESS.apiGetOnePosition}&positionId=${id}`) - const data = await res.json() - setData(data) + const res = await funGetOnePosition(id) + if (res.success) { + setData(res.data) + } else { + toast.error(res.message) + } } catch (error) { console.error(error) + toast.error("Gagal mendapatkan jabatan, coba lagi nanti"); } } async function onSubmit() { try { - const res = await fetch(API_ADDRESS.apiUpdatePosition, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - id: data.id, - name: data.name, - idGroup: data.idGroup, - }), + const res = await funEditPosition(id, { + name: data.name, + idGroup: data.idGroup }) - const respon = await res.json() - - if (res.status == 200) { - toast.success(respon.message) + if (res.success) { + toast.success(res.message); + onUpdated(true); + onCLose(); } else { - toast.error(respon.message) + onUpdated(false); + toast.error(res.message) } - onUpdated(true) - onCLose(); } catch (error) { toast.error('Error'); + toast.error("Edit jabatan gagal, coba lagi nanti"); } } @@ -86,28 +85,20 @@ export default function DrawerDetailPosition({ onUpdated, id, isActive }: { 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) { + const res = await funEditStatusPosition(id, { isActive: isActive }) + if (res.success) { + toast.success(res.message); onUpdated(true); } else { onUpdated(false); + toast.error(res.message) } } setModal(false); } catch (error) { console.log(error); setModal(false); - toast.error("Terjadi kesalahan"); + toast.error("Edit jabatan gagal, coba lagi nanti"); onUpdated(false); } } diff --git a/src/module/position/component/ui/drawer_list_position.tsx b/src/module/position/ui/drawer_list_position.tsx similarity index 80% rename from src/module/position/component/ui/drawer_list_position.tsx rename to src/module/position/ui/drawer_list_position.tsx index 55972d9..9859ae8 100644 --- a/src/module/position/component/ui/drawer_list_position.tsx +++ b/src/module/position/ui/drawer_list_position.tsx @@ -7,6 +7,7 @@ import { useEffect, useState } from "react"; import toast from "react-hot-toast"; import { IoAddCircle } from "react-icons/io5"; import { RiFilter2Line } from "react-icons/ri"; +import { funCreatePosition } from "../lib/api_position"; export default function DrawerListPosition({ onCreated }: { onCreated: (val: boolean) => void }) { @@ -40,29 +41,42 @@ export default function DrawerListPosition({ onCreated }: { onCreated: (val: boo async function onSubmit() { try { - const res = await fetch(API_ADDRESS.apiCreatePosition, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - name: listData.name, - idGroup: listData.idGroup - }) + // const res = await fetch(API_ADDRESS.apiCreatePosition, { + // method: 'POST', + // headers: { + // 'Content-Type': 'application/json' + // }, + // body: JSON.stringify({ + // name: listData.name, + // idGroup: listData.idGroup + // }) + // }) + + // if (!res.ok) { + // const errorData = await res.json(); + // if (errorData.message === "Position sudah ada") { + // toast.error('Gagal! Position sudah ada'); + // } else { + // toast.error('Error'); + // } + // } else { + // setOpenDrawerGroup(false) + // toast.success('Sukses! data tersimpan') + // } + // onCreated(true) + const res = await funCreatePosition({ + name: listData.name, + idGroup: listData.idGroup }) - if (!res.ok) { - const errorData = await res.json(); - if (errorData.message === "Position sudah ada") { - toast.error('Gagal! Position sudah ada'); - } else { - toast.error('Error'); - } - } else { + if (res.success) { setOpenDrawerGroup(false) - toast.success('Sukses! data tersimpan') + toast.success(res.message) + onCreated(true) + } else { + toast.error(res.message) } - onCreated(true) + } catch (error) { toast.error('Error') } diff --git a/src/module/position/component/ui/list_position_active.tsx b/src/module/position/ui/list_position_active.tsx similarity index 84% rename from src/module/position/component/ui/list_position_active.tsx rename to src/module/position/ui/list_position_active.tsx index f84867f..bba7991 100644 --- a/src/module/position/component/ui/list_position_active.tsx +++ b/src/module/position/ui/list_position_active.tsx @@ -8,35 +8,31 @@ import toast from "react-hot-toast"; import _ from "lodash"; import { useShallowEffect } from "@mantine/hooks"; import { useSearchParams } from "next/navigation"; +import { funGetAllPosition } from "../lib/api_position"; +import { IDataPosition } from "../lib/type_position"; -type dataPosition = { - name: string; - idGroup: string; - group: string; - id: string; - isActive: boolean -}; -export default function ListPositionActive({ status }: { status: boolean }) { +export default function ListPositionActive() { const [openDrawer, setOpenDrawer] = useState(false); const [isData, setData] = useState(""); - const [isDataPosition, setDataPosition] = useState([]); + const [isDataPosition, setDataPosition] = useState([]); const [loading, setLoading] = useState(true); - const [selectId, setSelectId] = useState(null); - const [active, setActive] = useState(null) + const [selectId, setSelectId] = useState(''); + const [active, setActive] = useState(false) const [searchQuery, setSearchQuery] = useState('') const searchParams = useSearchParams() const group = searchParams.get('group') + const status = searchParams.get('active') async function getAllPosition() { try { setDataPosition([]); setLoading(true) - const res = await fetch(`${API_ADDRESS.apiGetAllPosition}&active=${status}&groupId=${group}&name=${searchQuery}`); - const data = await res.json(); - setDataPosition(data); + const res = await funGetAllPosition('?active=' + status + '&group=' + group + '&search=' + searchQuery) + setDataPosition(res.data); setLoading(false); } catch (error) { + toast.error("Gagal mendapatkan position, coba lagi nanti"); console.error(error); } finally { setLoading(false); diff --git a/src/module/position/component/ui/navbar_list_position.tsx b/src/module/position/ui/navbar_list_position.tsx similarity index 94% rename from src/module/position/component/ui/navbar_list_position.tsx rename to src/module/position/ui/navbar_list_position.tsx index c25ad65..a290e1c 100644 --- a/src/module/position/component/ui/navbar_list_position.tsx +++ b/src/module/position/ui/navbar_list_position.tsx @@ -20,7 +20,6 @@ export default function NavbarListPosition() { setOpen(false)}> { setOpen(false) - // toast.success('Sukses! data tersimpan') }} /> diff --git a/src/module/position/ui/tab_list_position.tsx b/src/module/position/ui/tab_list_position.tsx new file mode 100644 index 0000000..4132270 --- /dev/null +++ b/src/module/position/ui/tab_list_position.tsx @@ -0,0 +1,47 @@ +'use client' +import { Box, Tabs, rem } from '@mantine/core'; +import { IoCloseCircleOutline } from "react-icons/io5" +import { IoMdCheckmarkCircleOutline } from "react-icons/io" +import ListPositionActive from './list_position_active'; +import { useRouter, useSearchParams } from 'next/navigation'; + +export default function TabListPosition() { + const iconStyle = { width: rem(20), height: rem(20) }; + const router = useRouter() + const searchParams = useSearchParams() + const status = searchParams.get('active') + + return ( + + + + } + onClick={() => { router.push("/position?active=true") }} + > + Aktif + + } + onClick={() => { router.push("/position?active=false") }} + > + Tidak Aktif + + + + + + ); +} + diff --git a/src/module/position/view/view_list_position.tsx b/src/module/position/view/view_list_position.tsx deleted file mode 100644 index a74180d..0000000 --- a/src/module/position/view/view_list_position.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Box } from "@mantine/core"; -import NavbarListPosition from "../component/ui/navbar_list_position"; -import TabListGroup from "../component/tab_list_position"; - -export default function ViewListPosition() { - return ( - - - - - ); -} \ No newline at end of file