diff --git a/src/module/project/ui/add_detail_task_project.tsx b/src/module/project/ui/add_detail_task_project.tsx index 5219b26..5d4caf4 100644 --- a/src/module/project/ui/add_detail_task_project.tsx +++ b/src/module/project/ui/add_detail_task_project.tsx @@ -1,14 +1,15 @@ "use client" -import { useParams, useRouter } from 'next/navigation'; -import React, { useState } from 'react'; -import toast from 'react-hot-toast'; -import { funCreateDetailProject } from '../lib/api_project'; -import { Box, Button, Group, Input, rem, SimpleGrid, Stack, Text, TextInput } from '@mantine/core'; -import { LayoutNavbarNew, TEMA, WARNA } from '@/module/_global'; -import { DatePicker } from '@mantine/dates'; -import moment from 'moment'; +import { keyWibu, LayoutNavbarNew, TEMA } from '@/module/_global'; import LayoutModal from '@/module/_global/layout/layout_modal'; import { useHookstate } from '@hookstate/core'; +import { Box, Button, Group, rem, SimpleGrid, Stack, Text, TextInput } from '@mantine/core'; +import { DatePicker } from '@mantine/dates'; +import moment from 'moment'; +import { useParams, useRouter } from 'next/navigation'; +import { useState } from 'react'; +import toast from 'react-hot-toast'; +import { useWibuRealtime } from 'wibu-realtime'; +import { funCreateDetailProject } from '../lib/api_project'; export default function AddDetailTaskProject() { const [value, setValue] = useState<[Date | null, Date | null]>([null, null]); @@ -20,6 +21,10 @@ export default function AddDetailTaskProject() { const [touched, setTouched] = useState({ name: false, }); + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) function onVerification() { if (value[0] == null || value[1] == null) @@ -40,6 +45,10 @@ export default function AddDetailTaskProject() { }) if (res.success) { + setDataRealtime([{ + category: "project-detail-task", + id: param.id, + }]) toast.success(res.message) setOpenModal(false) router.push(`/project/${param.id}`) diff --git a/src/module/project/ui/add_file_detail_project.tsx b/src/module/project/ui/add_file_detail_project.tsx index c9d102f..befa6ea 100644 --- a/src/module/project/ui/add_file_detail_project.tsx +++ b/src/module/project/ui/add_file_detail_project.tsx @@ -1,28 +1,19 @@ "use client"; -import { LayoutDrawer, LayoutNavbarNew } from "@/module/_global"; -import { - Box, - Button, - Flex, - Group, - rem, - SimpleGrid, - Stack, - Text, -} from "@mantine/core"; -import React, { useRef, useState } from "react"; -import { useParams, useRouter } from "next/navigation"; -import toast from "react-hot-toast"; -import { IoIosArrowDropright } from "react-icons/io"; +import { keyWibu, LayoutDrawer, LayoutNavbarNew, TEMA } from "@/module/_global"; +import LayoutModal from "@/module/_global/layout/layout_modal"; +import { useHookstate } from "@hookstate/core"; +import { Box, Button, Flex, Group, rem, SimpleGrid, Stack, Text, } from "@mantine/core"; import { Dropzone } from "@mantine/dropzone"; import _ from "lodash"; -import ResultsFile from "./results_file"; +import { useParams, useRouter } from "next/navigation"; +import { useRef, useState } from "react"; +import toast from "react-hot-toast"; import { FaTrash } from "react-icons/fa6"; -import LayoutModal from "@/module/_global/layout/layout_modal"; -import { IListFileTaskProject } from "../lib/type_project"; +import { IoIosArrowDropright } from "react-icons/io"; import { funAddFileProject, funCekNamFileUploadProject } from "../lib/api_project"; -import { TEMA } from "@/module/_global"; -import { useHookstate } from "@hookstate/core"; +import { IListFileTaskProject } from "../lib/type_project"; +import ResultsFile from "./results_file"; +import { useWibuRealtime } from "wibu-realtime"; export default function AddFileDetailProject() { @@ -35,6 +26,10 @@ export default function AddFileDetailProject() { const [openDrawerFile, setOpenDrawerFile] = useState(false) const tema = useHookstate(TEMA) const openRef = useRef<() => void>(null) + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) function deleteFile(index: number) { setListFile([...listFile.filter((val, i) => i !== index)]) @@ -70,6 +65,10 @@ export default function AddFileDetailProject() { const response = await funAddFileProject(param.id, fd) console.group(response) if (response.success) { + setDataRealtime([{ + category: "project-detail-file", + id: param.id, + }]) toast.success(response.message) setFileForm([]) setListFile([]) diff --git a/src/module/project/ui/add_member_detail_project.tsx b/src/module/project/ui/add_member_detail_project.tsx index 198b6b2..01f1079 100644 --- a/src/module/project/ui/add_member_detail_project.tsx +++ b/src/module/project/ui/add_member_detail_project.tsx @@ -1,18 +1,19 @@ "use client" -import { useParams, useRouter } from 'next/navigation'; -import React, { useState } from 'react'; -import { IDataMemberProject, IDataMemberProjectDetail } from '../lib/type_project'; -import toast from 'react-hot-toast'; -import { funAddMemberProject, funGetAllMemberById, funGetOneProjectById } from '../lib/api_project'; -import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; -import { ActionIcon, Avatar, Box, Button, Center, Divider, Flex, Grid, Group, Indicator, rem, Skeleton, Stack, Text, TextInput } from '@mantine/core'; -import { LayoutNavbarNew, SkeletonList, SkeletonSingle, TEMA, WARNA } from '@/module/_global'; -import { FaCheck } from 'react-icons/fa6'; +import { keyWibu, LayoutNavbarNew, SkeletonList, TEMA } from '@/module/_global'; import LayoutModal from '@/module/_global/layout/layout_modal'; +import { useHookstate } from '@hookstate/core'; +import { Carousel } from '@mantine/carousel'; +import { ActionIcon, Avatar, Box, Button, Center, Divider, Flex, Grid, Group, Indicator, rem, Skeleton, Stack, Text, TextInput } from '@mantine/core'; +import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; +import { useParams, useRouter } from 'next/navigation'; +import { useState } from 'react'; +import toast from 'react-hot-toast'; +import { FaCheck } from 'react-icons/fa6'; import { HiMagnifyingGlass } from 'react-icons/hi2'; import { IoArrowBackOutline, IoClose } from 'react-icons/io5'; -import { Carousel } from '@mantine/carousel'; -import { useHookstate } from '@hookstate/core'; +import { useWibuRealtime } from 'wibu-realtime'; +import { funAddMemberProject, funGetAllMemberById, funGetOneProjectById } from '../lib/api_project'; +import { IDataMemberProject, IDataMemberProjectDetail } from '../lib/type_project'; export default function AddMemberDetailProject() { const router = useRouter() @@ -27,6 +28,10 @@ export default function AddMemberDetailProject() { const [searchQuery, setSearchQuery] = useState('') const tema = useHookstate(TEMA) const isMobile2 = useMediaQuery("(max-width: 438px)"); + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) async function getData() { @@ -99,6 +104,10 @@ export default function AddMemberDetailProject() { try { const res = await funAddMemberProject(param.id, { member: selectedFiles }); if (res.success) { + setDataRealtime([{ + category: "project-detail-anggota", + id: param.id, + }]) toast.success(res.message) router.back() } else { diff --git a/src/module/project/ui/cancel_project.tsx b/src/module/project/ui/cancel_project.tsx index e400067..4928419 100644 --- a/src/module/project/ui/cancel_project.tsx +++ b/src/module/project/ui/cancel_project.tsx @@ -1,12 +1,13 @@ "use client" -import { useParams, useRouter } from 'next/navigation'; -import React, { useState } from 'react'; -import toast from 'react-hot-toast'; -import { funCancelProject } from '../lib/api_project'; -import { Box, Button, rem, Stack, Textarea } from '@mantine/core'; -import { LayoutNavbarNew, TEMA} from '@/module/_global'; +import { keyWibu, LayoutNavbarNew, TEMA } from '@/module/_global'; import LayoutModal from '@/module/_global/layout/layout_modal'; import { useHookstate } from '@hookstate/core'; +import { Box, Button, rem, Stack, Textarea } from '@mantine/core'; +import { useParams, useRouter } from 'next/navigation'; +import { useState } from 'react'; +import toast from 'react-hot-toast'; +import { useWibuRealtime } from 'wibu-realtime'; +import { funCancelProject } from '../lib/api_project'; export default function CancelProject() { const router = useRouter() @@ -17,6 +18,10 @@ export default function CancelProject() { const [touched, setTouched] = useState({ reason: false, }); + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) function onVerification() { if (alasan == "") @@ -29,6 +34,10 @@ export default function CancelProject() { try { const res = await funCancelProject(param.id, { reason: alasan }) if (res.success) { + setDataRealtime([{ + category: "project-detail-status", + id: param.id, + }]) toast.success(res.message) router.push("/project") } else { diff --git a/src/module/project/ui/edit_task_project.tsx b/src/module/project/ui/edit_task_project.tsx index d747bd5..58503b1 100644 --- a/src/module/project/ui/edit_task_project.tsx +++ b/src/module/project/ui/edit_task_project.tsx @@ -1,5 +1,5 @@ "use client" -import { LayoutNavbarNew, TEMA } from '@/module/_global'; +import { keyWibu, LayoutNavbarNew, TEMA } from '@/module/_global'; import LayoutModal from '@/module/_global/layout/layout_modal'; import { useHookstate } from '@hookstate/core'; import { Box, Button, rem, Skeleton, Stack, TextInput } from '@mantine/core'; @@ -8,6 +8,7 @@ import { useParams, useRouter } from 'next/navigation'; import { useState } from 'react'; import toast from 'react-hot-toast'; import { funEditProject, funGetOneProjectById } from '../lib/api_project'; +import { useWibuRealtime } from 'wibu-realtime'; export default function EditTaskProject() { const router = useRouter() @@ -19,11 +20,19 @@ export default function EditTaskProject() { const [touched, setTouched] = useState({ name: false, }); + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) async function onSubmit() { try { const res = await funEditProject(param.id, { name }) if (res.success) { + setDataRealtime([{ + category: "project-detail", + id: param.id, + }]) toast.success(res.message) router.push("./") } else { diff --git a/src/module/project/ui/list_anggota_detail_project.tsx b/src/module/project/ui/list_anggota_detail_project.tsx index ed459c4..9759377 100644 --- a/src/module/project/ui/list_anggota_detail_project.tsx +++ b/src/module/project/ui/list_anggota_detail_project.tsx @@ -1,16 +1,17 @@ 'use client' -import { globalRole, LayoutDrawer, SkeletonList, SkeletonSingle, TEMA } from '@/module/_global'; -import { Avatar, Box, Divider, Flex, Grid, Group, SimpleGrid, Stack, Text } from '@mantine/core'; -import React, { useState } from 'react'; -import { funDeleteMemberProject, funGetOneProjectById } from '../lib/api_project'; -import toast from 'react-hot-toast'; -import { useParams, useRouter } from 'next/navigation'; -import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; -import { IDataMemberProject } from '../lib/type_project'; -import { FaUser } from 'react-icons/fa6'; -import { IoIosCloseCircle } from 'react-icons/io'; +import { globalRole, keyWibu, LayoutDrawer, SkeletonList, TEMA } from '@/module/_global'; import LayoutModal from '@/module/_global/layout/layout_modal'; import { useHookstate } from '@hookstate/core'; +import { Avatar, Box, Divider, Flex, Grid, Group, SimpleGrid, Stack, Text } from '@mantine/core'; +import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; +import { useParams, useRouter } from 'next/navigation'; +import { useState } from 'react'; +import toast from 'react-hot-toast'; +import { FaUser } from 'react-icons/fa6'; +import { IoIosCloseCircle } from 'react-icons/io'; +import { useWibuRealtime } from 'wibu-realtime'; +import { funDeleteMemberProject, funGetOneProjectById } from '../lib/api_project'; +import { IDataMemberProject } from '../lib/type_project'; export default function ListAnggotaDetailProject() { @@ -25,6 +26,11 @@ export default function ListAnggotaDetailProject() { const tema = useHookstate(TEMA) const [reason, setReason] = useState("") const isMobile2 = useMediaQuery("(max-width: 438px)"); + const isMobile = useMediaQuery('(max-width: 369px)'); + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) async function getOneDataCancel() { try { @@ -45,9 +51,9 @@ export default function ListAnggotaDetailProject() { getOneDataCancel(); }, [param.id]) - async function getOneData() { + async function getOneData(loading: boolean) { try { - setLoading(true) + setLoading(loading) const res = await funGetOneProjectById(param.id, 'member'); if (res.success) { setData(res.data) @@ -64,7 +70,7 @@ export default function ListAnggotaDetailProject() { } useShallowEffect(() => { - getOneData(); + getOneData(true); }, [param.id]) @@ -72,9 +78,13 @@ export default function ListAnggotaDetailProject() { try { const res = await funDeleteMemberProject(param.id, { idUser: dataChoose.id }); if (res.success) { + setDataRealtime([{ + category: "project-detail-anggota", + id: param.id, + }]) toast.success(res.message) setDataChoose({ id: '', name: '' }) - getOneData() + getOneData(false) setOpenDrawer(false) } else { toast.error(res.message) @@ -84,7 +94,14 @@ export default function ListAnggotaDetailProject() { toast.error("Gagal menghapus anggota Kegiatan, coba lagi nanti"); } } - const isMobile = useMediaQuery('(max-width: 369px)'); + + useShallowEffect(() => { + if (dataRealTime && dataRealTime.some((i: any) => i.category == 'project-detail-anggota' && i.id == param.id)) { + getOneData(false) + } else if (dataRealTime && dataRealTime.some((i: any) => i.category == 'project-detail-status' && i.id == param.id)) { + getOneDataCancel() + } + }, [dataRealTime]) return ( @@ -128,11 +145,11 @@ export default function ListAnggotaDetailProject() { - {v.name} - {v.email} + {v.name} + {v.email} diff --git a/src/module/project/ui/list_file_detail_project.tsx b/src/module/project/ui/list_file_detail_project.tsx index 88ad231..cc07271 100644 --- a/src/module/project/ui/list_file_detail_project.tsx +++ b/src/module/project/ui/list_file_detail_project.tsx @@ -1,16 +1,17 @@ 'use client' -import { LayoutDrawer, LayoutModalViewFile, TEMA } from '@/module/_global'; -import { Box, Center, Flex, Grid, Group, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core'; -import React, { useState } from 'react'; -import toast from 'react-hot-toast'; -import { funDeleteFileProject, funGetOneProjectById } from '../lib/api_project'; -import { useParams } from 'next/navigation'; -import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; -import { IDataFileProject } from '../lib/type_project'; -import { BsFileTextFill, BsFiletypeCsv, BsFiletypeHeic, BsFiletypeJpg, BsFiletypePdf, BsFiletypePng } from 'react-icons/bs'; +import { keyWibu, LayoutDrawer, LayoutModalViewFile, TEMA } from '@/module/_global'; import LayoutModal from '@/module/_global/layout/layout_modal'; -import { FaTrash } from 'react-icons/fa6'; import { useHookstate } from '@hookstate/core'; +import { Box, Flex, Grid, Group, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core'; +import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; +import { useParams } from 'next/navigation'; +import { useState } from 'react'; +import toast from 'react-hot-toast'; +import { BsFileTextFill, BsFiletypeCsv, BsFiletypeHeic, BsFiletypeJpg, BsFiletypePdf, BsFiletypePng } from 'react-icons/bs'; +import { FaTrash } from 'react-icons/fa6'; +import { useWibuRealtime } from 'wibu-realtime'; +import { funDeleteFileProject, funGetOneProjectById } from '../lib/api_project'; +import { IDataFileProject } from '../lib/type_project'; export default function ListFileDetailProject() { const [isData, setData] = useState([]) @@ -26,6 +27,10 @@ export default function ListFileDetailProject() { const tema = useHookstate(TEMA) const isMobile = useMediaQuery("(max-width: 350px)"); const [reason, setReason] = useState("") + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) async function getOneDataCancel() { try { @@ -46,9 +51,9 @@ export default function ListFileDetailProject() { getOneDataCancel(); }, [param.id]) - async function getOneData() { + async function getOneData(loading: boolean) { try { - setLoading(true) + setLoading(loading) const res = await funGetOneProjectById(param.id, 'file'); if (res.success) { setData(res.data) @@ -65,7 +70,7 @@ export default function ListFileDetailProject() { } useShallowEffect(() => { - getOneData(); + getOneData(true); }, [param.id]) @@ -73,8 +78,12 @@ export default function ListFileDetailProject() { try { const res = await funDeleteFileProject(idData); if (res.success) { + setDataRealtime([{ + category: "project-detail-file", + id: param.id, + }]) toast.success(res.message) - getOneData() + getOneData(false) setIdData("") setIdStorage("") setOpenDrawer(false) @@ -88,6 +97,14 @@ export default function ListFileDetailProject() { } + useShallowEffect(() => { + if (dataRealTime && dataRealTime.some((i: any) => i.category == 'project-detail-file' && i.id == param.id)) { + getOneData(false) + } else if (dataRealTime && dataRealTime.some((i: any) => i.category == 'project-detail-status' && i.id == param.id)) { + getOneDataCancel() + } + }, [dataRealTime]) + return ( <> diff --git a/src/module/project/ui/list_project.tsx b/src/module/project/ui/list_project.tsx index adf23f3..3e6ae5c 100644 --- a/src/module/project/ui/list_project.tsx +++ b/src/module/project/ui/list_project.tsx @@ -1,17 +1,16 @@ "use client" -import { currentScroll, globalRole, SkeletonList, TEMA } from '@/module/_global'; +import { currentScroll, globalNotifPage, globalRole, ReloadButtonTop, SkeletonList, TEMA } from '@/module/_global'; +import { useHookstate } from '@hookstate/core'; import { ActionIcon, Avatar, Badge, Box, Card, Center, Divider, Flex, Grid, Group, Skeleton, Text, TextInput, Title } from '@mantine/core'; +import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; +import _ from 'lodash'; import { useRouter, useSearchParams } from 'next/navigation'; -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; +import toast from 'react-hot-toast'; import { HiMagnifyingGlass, HiMiniPresentationChartBar, HiOutlineListBullet, HiSquares2X2 } from 'react-icons/hi2'; import { MdAccountCircle } from 'react-icons/md'; -import { RiCircleFill } from 'react-icons/ri'; import { funGetAllProject } from '../lib/api_project'; -import toast from 'react-hot-toast'; -import { useMediaQuery, useShallowEffect } from '@mantine/hooks'; import { IDataProject } from '../lib/type_project'; -import { useHookstate } from '@hookstate/core'; -import _ from 'lodash'; export default function ListProject() { const [isList, setIsList] = useState(false) @@ -30,6 +29,8 @@ export default function ListProject() { const [totalData, setTotalData] = useState(0) const isMobile = useMediaQuery('(max-width: 369px)'); const paddingLift = useMediaQuery('(max-width: 505px)') + const [isRefresh, setRefresh] = useState(false) + const notifLoadPage = useHookstate(globalNotifPage) const handleList = () => { setIsList(!isList) @@ -39,6 +40,9 @@ export default function ListProject() { try { if (loading) setLoading(true) + if (isPage == 1) { + setData([]) + } const response = await funGetAllProject('?status=' + status + '&search=' + searchQuery + '&group=' + group + '&page=' + isPage) if (response.success) { setNameGroup(response.filter.name) @@ -46,7 +50,7 @@ export default function ListProject() { if (isPage == 1) { setData(response.data) } else { - setData([...isData, ...response.data]) + setData((isData) => [...isData, ...response.data]) } } else { toast.error(response.message); @@ -92,8 +96,34 @@ export default function ListProject() { }; }, [containerRef, isPage]); + useShallowEffect(() => { + if (notifLoadPage.get().category == 'project' && notifLoadPage.get().load == true) { + setRefresh(true) + } + }, [notifLoadPage.get().load]) + + function onRefresh() { + notifLoadPage.set({ + category: '', + load: false + }) + setRefresh(false) + setPage(1) + setTimeout(() => { + fetchData(true) + }, 500) + } + return ( + { + isRefresh && + { onRefresh() }} + title='UPDATE' + /> + + } ( - + )) : @@ -147,59 +177,59 @@ export default function ListProject() { Tidak ada Kegiatan : - isData.map((v, i) => { - return ( - - router.push(`/project/${v.id}`)}> - - -
- - - -
-
-
- - - - - - {v.title} - - + isData.map((v, i) => { + return ( + + router.push(`/project/${v.id}`)}> + + +
+ + + +
+
+
+ + + + + + {v.title} + - - -
- -
- ); - }) - } +
+
+
+
+ +
+ ); + }) + }
) : ( diff --git a/src/module/project/ui/list_tugas_detail_project.tsx b/src/module/project/ui/list_tugas_detail_project.tsx index 5babd36..e32f21e 100644 --- a/src/module/project/ui/list_tugas_detail_project.tsx +++ b/src/module/project/ui/list_tugas_detail_project.tsx @@ -1,17 +1,18 @@ 'use client' -import { LayoutDrawer, SkeletonDetailListTugasTask, TEMA } from '@/module/_global'; +import { 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 React, { useState } from 'react'; +import { useShallowEffect } from '@mantine/hooks'; +import { useParams, useRouter } from 'next/navigation'; +import { useState } from 'react'; import toast from 'react-hot-toast'; import { AiOutlineFileDone, AiOutlineFileSync } from 'react-icons/ai'; -import { funDeleteDetailProject, funGetOneProjectById, funUpdateStatusProject } from '../lib/api_project'; -import { useParams, useRouter } from 'next/navigation'; -import { useShallowEffect } from '@mantine/hooks'; -import { IDataListTaskProject } from '../lib/type_project'; -import { useHookstate } from '@hookstate/core'; -import { globalRefreshProject, valStatusDetailProject } from '../lib/val_project'; import { FaCheck, FaPencil, FaTrash } from 'react-icons/fa6'; -import LayoutModal from '@/module/_global/layout/layout_modal'; +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'; export default function ListTugasDetailProject() { const [isData, setData] = useState([]) @@ -26,6 +27,10 @@ export default function ListTugasDetailProject() { const router = useRouter() const tema = useHookstate(TEMA) const [reason, setReason] = useState("") + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) async function getOneDataCancel() { try { @@ -46,9 +51,9 @@ export default function ListTugasDetailProject() { getOneDataCancel(); }, [param.id]) - async function getOneData() { + async function getOneData(loading: boolean) { try { - setLoading(true) + setLoading(loading) const res = await funGetOneProjectById(param.id, 'task'); if (res.success) { setData(res.data) @@ -65,15 +70,19 @@ export default function ListTugasDetailProject() { } useShallowEffect(() => { - getOneData(); + getOneData(true); }, [param.id]) async function onDelete() { try { const res = await funDeleteDetailProject(idData, { idProject: param.id }); if (res.success) { + setDataRealtime([{ + category: "project-detail-task", + id: param.id, + }]) toast.success(res.message); - getOneData(); + getOneData(false); setIdData("") setOpenDrawer(false) refresh.set(true) @@ -90,8 +99,12 @@ export default function ListTugasDetailProject() { try { const res = await funUpdateStatusProject(idData, { status: val, idProject: param.id }); if (res.success) { + setDataRealtime([{ + category: "project-detail-task", + id: param.id, + }]) toast.success(res.message); - getOneData(); + getOneData(false); setIdData("") setOpenDrawer(false) setOpenDrawerStatus(false) @@ -105,6 +118,15 @@ export default function ListTugasDetailProject() { } } + useShallowEffect(() => { + if (dataRealTime && dataRealTime.some((i: any) => i.category == 'project-detail-task' && i.id == param.id)) { + refresh.set(true) + getOneData(false) + } else if (dataRealTime && dataRealTime.some((i: any) => i.category == 'project-detail-status' && i.id == param.id)) { + getOneDataCancel() + } + }, [dataRealTime]) + return ( <> @@ -124,21 +146,21 @@ export default function ListTugasDetailProject() { { loading ? <> - + : isData.length === 0 ? Tidak ada tugas : isData.map((item, index) => { return ( - { + { setIdData(item.id) setStatusData(item.status) reason == null ? setOpenDrawer(true) - : setOpenDrawer(false) + : setOpenDrawer(false) }} my={18}> - @@ -187,7 +209,7 @@ export default function ListTugasDetailProject() { - + ) }) @@ -203,7 +225,7 @@ export default function ListTugasDetailProject() { alignItems: 'flex-start', }} > - { setOpenDrawerStatus(true) }} justify={'center'} align={'center'} direction={'column'} pb={20}> + { setOpenDrawerStatus(true) }} justify={'center'} align={'center'} direction={'column'} pb={20}> @@ -245,36 +267,36 @@ export default function ListTugasDetailProject() { setOpenDrawerStatus(false)}> - { - valStatusDetailProject.map((item, index) => { - return ( - { onUpdateStatus(item.value) }}> - - - - {item.name} - - - - {statusData === item.value ? : ""} + { + valStatusDetailProject.map((item, index) => { + return ( + { onUpdateStatus(item.value) }}> + + + + {item.name} - - - - ) - }) - } + + + {statusData === item.value ? : ""} + + + + + ) + }) + } diff --git a/src/module/project/ui/navbar_detail_project.tsx b/src/module/project/ui/navbar_detail_project.tsx index 6683118..0568bf5 100644 --- a/src/module/project/ui/navbar_detail_project.tsx +++ b/src/module/project/ui/navbar_detail_project.tsx @@ -1,16 +1,17 @@ 'use client' -import { globalRole, LayoutDrawer, LayoutNavbarNew, TEMA } from '@/module/_global'; +import { globalRole, keyWibu, LayoutDrawer, LayoutNavbarNew, TEMA } from '@/module/_global'; +import { useHookstate } from '@hookstate/core'; import { ActionIcon, Box, Flex, SimpleGrid, Stack, Text } from '@mantine/core'; +import { useShallowEffect } from '@mantine/hooks'; import { useParams, useRouter } from 'next/navigation'; -import React, { useState } from 'react'; +import { useState } from 'react'; import toast from 'react-hot-toast'; import { FaFileCirclePlus, FaPencil, FaUsers } from 'react-icons/fa6'; import { HiMenu } from 'react-icons/hi'; import { IoAddCircle } from 'react-icons/io5'; import { MdCancel } from 'react-icons/md'; import { funGetOneProjectById } from '../lib/api_project'; -import { useShallowEffect } from '@mantine/hooks'; -import { useHookstate } from '@hookstate/core'; +import { useWibuRealtime } from 'wibu-realtime'; export default function NavbarDetailProject() { const router = useRouter() @@ -20,6 +21,10 @@ export default function NavbarDetailProject() { const roleLogin = useHookstate(globalRole) const tema = useHookstate(TEMA) const [reason, setReason] = useState("") + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) async function getOneData() { try { @@ -41,6 +46,12 @@ export default function NavbarDetailProject() { getOneData(); }, [param.id]) + useShallowEffect(() => { + if (dataRealTime && dataRealTime.some((i: any) => (i.category == 'project-detail' || i.category == 'project-detail-status') && i.id == param.id)) { + getOneData() + } + }, [dataRealTime]) + return ( <> { - getOneData(); + getOneData(true); }, [param.id]) + useShallowEffect(() => { + if (dataRealTime && dataRealTime.some((i: any) => i.category == 'project-detail-status' && i.id == param.id)) { + getOneDataCancel() + getOneData(false) + } + }, [dataRealTime]) + return ( <>