diff --git a/src/app/(application)/project/[id]/layout.tsx b/src/app/(application)/project/[id]/layout.tsx new file mode 100644 index 0000000..c3f8779 --- /dev/null +++ b/src/app/(application)/project/[id]/layout.tsx @@ -0,0 +1,11 @@ +import { WrapLayoutProject } from "@/module/project"; + +export default async function Layout({ children }: { children: React.ReactNode }) { + return ( + <> + + {children} + + + ); +} \ No newline at end of file diff --git a/src/module/project/index.ts b/src/module/project/index.ts index 090f969..1c33e04 100644 --- a/src/module/project/index.ts +++ b/src/module/project/index.ts @@ -14,6 +14,7 @@ import CancelProject from "./ui/cancel_project"; import AddMemberDetailProject from "./ui/add_member_detail_project"; import CreateProject from "./ui/create_project"; import AddFileDetailProject from "./ui/add_file_detail_project"; +import WrapLayoutProject from "./ui/wrap_project"; export { ViewDateEndTask } export { CreateUsersProject } @@ -29,4 +30,5 @@ export { AddDetailTaskProject } export { CancelProject } export { AddMemberDetailProject } export { CreateProject } -export { AddFileDetailProject } \ No newline at end of file +export { AddFileDetailProject } +export { WrapLayoutProject } \ No newline at end of file diff --git a/src/module/project/lib/val_project.ts b/src/module/project/lib/val_project.ts index 1566b5b..70c2d24 100644 --- a/src/module/project/lib/val_project.ts +++ b/src/module/project/lib/val_project.ts @@ -3,6 +3,7 @@ import { IFormMemberProject } from "./type_project"; export const globalRefreshProject = hookstate(false) export const globalMemberProject = hookstate([]); +export const globalIsMemberProject = hookstate(false) export const valStatusDetailProject = [ { diff --git a/src/module/project/ui/list_anggota_detail_project.tsx b/src/module/project/ui/list_anggota_detail_project.tsx index e5b5220..b1a78cb 100644 --- a/src/module/project/ui/list_anggota_detail_project.tsx +++ b/src/module/project/ui/list_anggota_detail_project.tsx @@ -111,7 +111,7 @@ export default function ListAnggotaDetailProject() { return ( - Anggota Terpilih + Anggota Total {isData.length} Anggota diff --git a/src/module/project/ui/list_file_detail_project.tsx b/src/module/project/ui/list_file_detail_project.tsx index 2e0c424..9a65f43 100644 --- a/src/module/project/ui/list_file_detail_project.tsx +++ b/src/module/project/ui/list_file_detail_project.tsx @@ -1,5 +1,5 @@ 'use client' -import { keyWibu, LayoutDrawer, LayoutModalViewFile, TEMA } from '@/module/_global'; +import { globalRole, keyWibu, LayoutDrawer, LayoutModalViewFile, TEMA } from '@/module/_global'; import LayoutModal from '@/module/_global/layout/layout_modal'; import { useHookstate } from '@hookstate/core'; import { Box, Flex, Grid, Group, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core'; @@ -12,6 +12,7 @@ import { FaTrash } from 'react-icons/fa6'; import { useWibuRealtime } from 'wibu-realtime'; import { funDeleteFileProject, funGetOneProjectById } from '../lib/api_project'; import { IDataFileProject } from '../lib/type_project'; +import { globalIsMemberProject } from '../lib/val_project'; export default function ListFileDetailProject() { const [isData, setData] = useState([]) @@ -26,6 +27,8 @@ export default function ListFileDetailProject() { const [isOpenModalView, setOpenModalView] = useState(false) const [isExtension, setExtension] = useState('') const tema = useHookstate(TEMA) + const roleLogin = useHookstate(globalRole) + const memberProject = useHookstate(globalIsMemberProject) const isMobile = useMediaQuery("(max-width: 350px)"); const [reason, setReason] = useState("") const [dataRealTime, setDataRealtime] = useWibuRealtime({ @@ -212,18 +215,22 @@ export default function ListFileDetailProject() { - { - reason == null ? - setOpenModal(true) - : setOpenModal(false) - }} justify={'center'} align={'center'} direction={'column'} > - - - - - Hapus file - - + { + (roleLogin.get() == "user" || roleLogin.get() == "coadmin") && !memberProject.get() ? <> + : + { + reason == null ? + setOpenModal(true) + : setOpenModal(false) + }} justify={'center'} align={'center'} direction={'column'} > + + + + + Hapus file + + + } diff --git a/src/module/project/ui/list_tugas_detail_project.tsx b/src/module/project/ui/list_tugas_detail_project.tsx index 2e8fd48..c14c45a 100644 --- a/src/module/project/ui/list_tugas_detail_project.tsx +++ b/src/module/project/ui/list_tugas_detail_project.tsx @@ -1,8 +1,8 @@ 'use client' -import { keyWibu, LayoutDrawer, SkeletonDetailListTugasTask, TEMA } from '@/module/_global'; +import { globalRole, keyWibu, LayoutDrawer, SkeletonDetailListTugasTask, TEMA } from '@/module/_global'; import LayoutModal from '@/module/_global/layout/layout_modal'; import { useHookstate } from '@hookstate/core'; -import { Box, Center, Checkbox, Divider, Flex, Grid, Group, SimpleGrid, Stack, Text } from '@mantine/core'; +import { Box, Center, Checkbox, Divider, Flex, Grid, Group, SimpleGrid, Stack, Text, Loader } from '@mantine/core'; import { useShallowEffect } from '@mantine/hooks'; import { useParams, useRouter } from 'next/navigation'; import { useState } from 'react'; @@ -12,7 +12,7 @@ import { FaCheck, FaPencil, FaTrash } from 'react-icons/fa6'; import { useWibuRealtime } from 'wibu-realtime'; import { funDeleteDetailProject, funGetOneProjectById, funUpdateStatusProject } from '../lib/api_project'; import { IDataListTaskProject } from '../lib/type_project'; -import { globalRefreshProject, valStatusDetailProject } from '../lib/val_project'; +import { globalIsMemberProject, globalRefreshProject, valStatusDetailProject } from '../lib/val_project'; export default function ListTugasDetailProject() { const [isData, setData] = useState([]) @@ -27,6 +27,10 @@ export default function ListTugasDetailProject() { const [loadingDelete, setLoadingDelete] = useState(false) const router = useRouter() const tema = useHookstate(TEMA) + const roleLogin = useHookstate(globalRole) + const memberProject = useHookstate(globalIsMemberProject) + const [loadingStatus, setLoadingStatus] = useState(false) + const [pilihStatus, setPilihStatus] = useState(0) const [reason, setReason] = useState("") const [dataRealTime, setDataRealtime] = useWibuRealtime({ WIBU_REALTIME_TOKEN: keyWibu, @@ -102,6 +106,8 @@ export default function ListTugasDetailProject() { async function onUpdateStatus(val: number) { try { + setLoadingStatus(true) + setPilihStatus(val) const res = await funUpdateStatusProject(idData, { status: val, idProject: param.id }); if (res.success) { setDataRealtime([{ @@ -120,6 +126,8 @@ export default function ListTugasDetailProject() { } catch (error) { console.error(error); toast.error("Gagal update status tugas Kegiatan, coba lagi nanti"); + } finally { + setLoadingStatus(false) } } @@ -158,11 +166,15 @@ export default function ListTugasDetailProject() { return ( { - setIdData(item.id) - setStatusData(item.status) - reason == null ? - setOpenDrawer(true) - : setOpenDrawer(false) + if (!memberProject.get() && ((roleLogin.get() == "user" || roleLogin.get() == "coadmin"))) { + setOpenDrawer(false) + } else { + setIdData(item.id) + setStatusData(item.status) + reason == null ? + setOpenDrawer(true) + : setOpenDrawer(false) + } }} my={18}> { return ( - { onUpdateStatus(item.value) }}> + { + if (!loadingStatus) { + onUpdateStatus(item.value) + } + }}> - {statusData === item.value ? : ""} + { + loadingStatus && pilihStatus == item.value ? + : + statusData === item.value ? : "" + } diff --git a/src/module/project/ui/navbar_detail_project.tsx b/src/module/project/ui/navbar_detail_project.tsx index dcbaba7..2444f20 100644 --- a/src/module/project/ui/navbar_detail_project.tsx +++ b/src/module/project/ui/navbar_detail_project.tsx @@ -12,6 +12,7 @@ import { IoAddCircle } from 'react-icons/io5'; import { MdCancel } from 'react-icons/md'; import { useWibuRealtime } from 'wibu-realtime'; import { funGetOneProjectById } from '../lib/api_project'; +import { globalIsMemberProject } from '../lib/val_project'; export default function NavbarDetailProject() { const router = useRouter() @@ -20,6 +21,7 @@ export default function NavbarDetailProject() { const [grup, setGrup] = useState("") const [isOpen, setOpen] = useState(false) const roleLogin = useHookstate(globalRole) + const memberProject = useHookstate(globalIsMemberProject) const tema = useHookstate(TEMA) const [reason, setReason] = useState("") const [dataRealTime, setDataRealtime] = useWibuRealtime({ @@ -57,16 +59,18 @@ export default function NavbarDetailProject() { return ( <> { setOpen(true) }} - > - - + (roleLogin.get() == "user" || roleLogin.get() == "coadmin") && !memberProject.get() ? <> + : + { setOpen(true) }} + > + + } /> setOpen(false)}> diff --git a/src/module/project/ui/wrap_project.tsx b/src/module/project/ui/wrap_project.tsx new file mode 100644 index 0000000..f1e6643 --- /dev/null +++ b/src/module/project/ui/wrap_project.tsx @@ -0,0 +1,28 @@ +'use client' +import { useHookstate } from "@hookstate/core"; +import { useShallowEffect } from "@mantine/hooks"; +import { useParams } from "next/navigation"; +import { funGetUserByCookies } from "@/module/auth"; +import { globalIsMemberProject } from "../lib/val_project"; +import { funGetOneProjectById } from "../lib/api_project"; + +export default function WrapLayoutProject({ children }: { children: React.ReactNode }) { + const isMember = useHookstate(globalIsMemberProject) + const param = useParams<{ id: string }>() + + const getData = async () => { + const res = await funGetOneProjectById(param.id, 'member'); + const login = await funGetUserByCookies() + const cekMember = res.data.some((i: any) => i.idUser == login.id) + isMember.set(cekMember) + } + + useShallowEffect(() => { + getData() + }, []) + return ( + <> + {children} + + ); +} \ No newline at end of file