From ee43572183d3a08ebfb6d311915947b3708616a7 Mon Sep 17 00:00:00 2001 From: amel Date: Tue, 15 Oct 2024 12:49:19 +0800 Subject: [PATCH 1/2] upd: kegiatan Deskripsi: - update realtime refresh - update realtime per aksi per kegiatan No Issues --- .../project/ui/add_detail_task_project.tsx | 25 ++- .../project/ui/add_file_detail_project.tsx | 39 +++-- .../project/ui/add_member_detail_project.tsx | 31 ++-- src/module/project/ui/cancel_project.tsx | 21 ++- src/module/project/ui/edit_task_project.tsx | 11 +- .../ui/list_anggota_detail_project.tsx | 57 ++++--- .../project/ui/list_file_detail_project.tsx | 45 ++++-- src/module/project/ui/list_project.tsx | 152 +++++++++++------- .../project/ui/list_tugas_detail_project.tsx | 120 ++++++++------ .../project/ui/navbar_detail_project.tsx | 19 ++- .../project/ui/progress_detail_project.tsx | 34 ++-- 11 files changed, 349 insertions(+), 205 deletions(-) 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 ( <> From 54a2884b317cc159e467e797e842259c91f64978 Mon Sep 17 00:00:00 2001 From: amel Date: Tue, 15 Oct 2024 22:07:27 +0800 Subject: [PATCH 2/2] upd: document Deskripsi: - update realtime document No Issues --- .../document/ui/drawer_cut_documents.tsx | 70 +++++--------- .../ui/drawer_menu_document_division.tsx | 38 +++++--- src/module/document/ui/drawer_more.tsx | 33 +++++-- .../document/ui/drawer_share_document.tsx | 25 +---- .../document/ui/navbar_document_division.tsx | 96 ++++++++----------- 5 files changed, 117 insertions(+), 145 deletions(-) diff --git a/src/module/document/ui/drawer_cut_documents.tsx b/src/module/document/ui/drawer_cut_documents.tsx index 7bd5ac4..16a70c0 100644 --- a/src/module/document/ui/drawer_cut_documents.tsx +++ b/src/module/document/ui/drawer_cut_documents.tsx @@ -1,47 +1,18 @@ -import { TEMA } from "@/module/_global"; -import { - Box, - Breadcrumbs, - Button, - Divider, - Flex, - Grid, - Group, - Modal, - ScrollArea, - Skeleton, - Text, - TextInput, -} from "@mantine/core"; -import React, { useState } from "react"; +import { keyWibu, TEMA } from "@/module/_global"; +import { useHookstate } from "@hookstate/core"; +import { Box, Breadcrumbs, Button, Divider, Flex, Grid, Group, Modal, ScrollArea, Skeleton, Text, TextInput, } 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 { FcFolder } from "react-icons/fc"; -import { - funCreateFolder, - funGetAllDocument, - funMoveDocument, -} from "../lib/api_document"; -import { useParams } from "next/navigation"; -import { - IDataDocument, - IFormDetailMoreItem, - IJalurItem, -} from "../lib/type_document"; -import { useMediaQuery, useShallowEffect } from "@mantine/hooks"; -import { MdFolder } from "react-icons/md"; -import router from "next/router"; import { GoChevronRight } from "react-icons/go"; -import { useHookstate } from "@hookstate/core"; +import { MdFolder } from "react-icons/md"; +import { funCreateFolder, funGetAllDocument } from "../lib/api_document"; +import { IDataDocument, IFormDetailMoreItem, IJalurItem, } from "../lib/type_document"; +import { useWibuRealtime } from "wibu-realtime"; -export default function DrawerCutDocuments({ - category, - onChoosePath, - data, -}: { - category: string; - data: IFormDetailMoreItem[]; - onChoosePath: (val: string) => void; -}) { +export default function DrawerCutDocuments({ category, onChoosePath, data, }: { category: string; data: IFormDetailMoreItem[]; onChoosePath: (val: string) => void; }) { const [opened, setOpened] = useState(false); const param = useParams<{ id: string }>(); const [path, setPath] = useState("home"); @@ -51,6 +22,10 @@ export default function DrawerCutDocuments({ const tema = useHookstate(TEMA); const [loading, setLoading] = useState(true); const isMobile = useMediaQuery("(max-width: 369px)"); + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) async function onCreateFolder() { try { @@ -60,7 +35,11 @@ export default function DrawerCutDocuments({ idDivision: param.id, }); if (res.success) { - getOneData(); + getOneData(false); + setDataRealtime([{ + category: "division-document", + id: path, + }]) } else { toast.error(res.message); } @@ -72,9 +51,9 @@ export default function DrawerCutDocuments({ setOpened(false); } - async function getOneData() { + async function getOneData(loading: boolean) { try { - setLoading(true); + setLoading(loading); const respon = await funGetAllDocument( "?division=" + param.id + "&path=" + path + "&category=folder" ); @@ -84,7 +63,6 @@ export default function DrawerCutDocuments({ } else { toast.error(respon.message); } - setLoading(false); } catch (error) { console.error(error); toast.error("Gagal mendapatkan item, coba lagi nanti"); @@ -94,7 +72,7 @@ export default function DrawerCutDocuments({ } useShallowEffect(() => { - getOneData(); + getOneData(true); }, [param.id, path]); return ( @@ -133,7 +111,7 @@ export default function DrawerCutDocuments({
- + } diff --git a/src/module/document/ui/drawer_menu_document_division.tsx b/src/module/document/ui/drawer_menu_document_division.tsx index beb8563..3539432 100644 --- a/src/module/document/ui/drawer_menu_document_division.tsx +++ b/src/module/document/ui/drawer_menu_document_division.tsx @@ -1,31 +1,33 @@ "use clent" -import { LayoutDrawer, TEMA } from '@/module/_global'; -import { ActionIcon, Box, Button, Center, Divider, Flex, Grid, Modal, Progress, rem, SimpleGrid, Stack, Text, TextInput } from '@mantine/core'; -import { useParams, useRouter, useSearchParams } from 'next/navigation'; -import React, { useRef, useState } from 'react'; -import toast from 'react-hot-toast'; -import { FaFolderClosed, FaRegImage } from 'react-icons/fa6'; -import { HiDocumentText } from 'react-icons/hi2'; -import { IoAddCircle, IoDocumentText } from 'react-icons/io5'; -import { funCreateFolder, funUploadFileDocument } from '../lib/api_document'; +import { keyWibu, LayoutDrawer, TEMA } from '@/module/_global'; import { useHookstate } from '@hookstate/core'; -import { globalRefreshDocument } from '../lib/val_document'; +import { ActionIcon, Box, Button, Flex, Grid, Modal, Progress, SimpleGrid, Stack, Text, TextInput } from '@mantine/core'; import { Dropzone } from '@mantine/dropzone'; import _ from 'lodash'; +import { useParams, useSearchParams } from 'next/navigation'; +import { useRef, useState } from 'react'; +import toast from 'react-hot-toast'; +import { FaFolderClosed } from 'react-icons/fa6'; +import { HiDocumentText } from 'react-icons/hi2'; +import { IoAddCircle } from 'react-icons/io5'; +import { useWibuRealtime } from 'wibu-realtime'; +import { funCreateFolder, funUploadFileDocument } from '../lib/api_document'; +import { globalRefreshDocument } from '../lib/val_document'; export default function DrawerMenuDocumentDivision() { const [openDrawerDocument, setOpenDrawerDocument] = useState(false) const [openModal, setOpenModal] = useState(false) - const router = useRouter() const param = useParams<{ id: string }>() const searchParams = useSearchParams() const path = searchParams.get('path') const refresh = useHookstate(globalRefreshDocument) const openRef = useRef<() => void>(null) - const [fileForm, setFileForm] = useState() const tema = useHookstate(TEMA) const [loading, setLoading] = useState(false) - + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) const [bodyFolder, setBodyFolder] = useState({ name: '', path: (path == undefined || path == '' || path == null) ? 'home' : path, @@ -37,6 +39,11 @@ export default function DrawerMenuDocumentDivision() { const res = await funCreateFolder(bodyFolder) if (!res.success) { toast.error(res.message) + } else { + setDataRealtime([{ + category: "division-document", + id: path, + }]) } } catch (error) { console.error(error); @@ -63,6 +70,11 @@ export default function DrawerMenuDocumentDivision() { if (!res.success) { toast.error(res.message) + } else { + setDataRealtime([{ + category: "division-document", + id: path, + }]) } setLoading(false) } catch (error) { diff --git a/src/module/document/ui/drawer_more.tsx b/src/module/document/ui/drawer_more.tsx index 6c42e71..56c6d3d 100644 --- a/src/module/document/ui/drawer_more.tsx +++ b/src/module/document/ui/drawer_more.tsx @@ -1,15 +1,16 @@ -import { LayoutDrawer, TEMA } from "@/module/_global"; -import { Box, Flex, Group, SimpleGrid, Stack, Text } from "@mantine/core"; -import React, { useState } from "react"; -import { LuFolders, LuFolderSymlink } from "react-icons/lu"; -import DrawerCutDocuments from "./drawer_cut_documents"; -import { IDataDocument, IFormDetailMoreItem } from "../lib/type_document"; -import toast from "react-hot-toast"; -import { funCopyDocument, funMoveDocument } from "../lib/api_document"; +import { keyWibu, LayoutDrawer, TEMA } from "@/module/_global"; import { useHookstate } from "@hookstate/core"; -import { globalRefreshDocument } from "../lib/val_document"; -import { useParams } from "next/navigation"; +import { Box, Flex, SimpleGrid, Stack, Text } from "@mantine/core"; import { useShallowEffect } from "@mantine/hooks"; +import { useParams } from "next/navigation"; +import { useState } from "react"; +import toast from "react-hot-toast"; +import { LuFolders, LuFolderSymlink } from "react-icons/lu"; +import { funCopyDocument, funMoveDocument } from "../lib/api_document"; +import { IDataDocument } from "../lib/type_document"; +import { globalRefreshDocument } from "../lib/val_document"; +import DrawerCutDocuments from "./drawer_cut_documents"; +import { useWibuRealtime } from "wibu-realtime"; export default function DrawerMore({ data }: { data: IDataDocument[] }) { const [isCut, setIsCut] = useState(false) @@ -18,12 +19,20 @@ export default function DrawerMore({ data }: { data: IDataDocument[] }) { const param = useParams<{ id: string }>() const [forbidCopy, setForbidCopy] = useState(true) const tema = useHookstate(TEMA) + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) async function onMoveItem(path: string) { try { const res = await funMoveDocument({ path, dataItem: data }) if (res.success) { + setDataRealtime([{ + category: "division-document", + id: path, + }]) toast.success(res.message) refresh.set(true) } else { @@ -41,6 +50,10 @@ export default function DrawerMore({ data }: { data: IDataDocument[] }) { try { const res = await funCopyDocument({ idDivision: param.id, path, dataItem: data }) if (res.success) { + setDataRealtime([{ + category: "division-document", + id: path, + }]) toast.success(res.message) refresh.set(true) } else { diff --git a/src/module/document/ui/drawer_share_document.tsx b/src/module/document/ui/drawer_share_document.tsx index 91c1311..77640ca 100644 --- a/src/module/document/ui/drawer_share_document.tsx +++ b/src/module/document/ui/drawer_share_document.tsx @@ -1,22 +1,7 @@ import { TEMA } from "@/module/_global"; -import { - funGetListDivisionByIdDivision, - IDataDivison, -} from "@/module/division_new"; +import { funGetListDivisionByIdDivision, IDataDivison, } from "@/module/division_new"; import { useHookstate } from "@hookstate/core"; -import { - ActionIcon, - Box, - Button, - Divider, - Flex, - Grid, - Group, - ScrollArea, - Skeleton, - Stack, - Text -} from "@mantine/core"; +import { ActionIcon, Box, Button, Divider, Flex, Grid, Group, ScrollArea, Skeleton, Stack, Text } from "@mantine/core"; import { useMediaQuery, useShallowEffect } from "@mantine/hooks"; import { useParams } from "next/navigation"; import { useState } from "react"; @@ -26,11 +11,7 @@ import { funShareDocument } from "../lib/api_document"; import { IShareDivision } from "../lib/type_document"; import { globalRefreshDocument } from "../lib/val_document"; -export default function DrawerShareDocument({ - data, -}: { - data: IShareDivision[]; -}) { +export default function DrawerShareDocument({ data, }: { data: IShareDivision[]; }) { const [selectedFiles, setSelectedFiles] = useState([]); const [isData, setData] = useState([]); const param = useParams<{ id: string }>(); diff --git a/src/module/document/ui/navbar_document_division.tsx b/src/module/document/ui/navbar_document_division.tsx index 3db2a16..7fe8071 100644 --- a/src/module/document/ui/navbar_document_division.tsx +++ b/src/module/document/ui/navbar_document_division.tsx @@ -1,58 +1,30 @@ "use client"; -import { - LayoutDrawer, - LayoutModalViewFile, - LayoutNavbarNew, - TEMA, -} from "@/module/_global"; -import { - ActionIcon, - Anchor, - Box, - Breadcrumbs, - Button, - Checkbox, - Divider, - Flex, - Grid, - Group, - Indicator, - Menu, - Modal, - rem, - Select, - SimpleGrid, - Skeleton, - Text, - TextInput, -} from "@mantine/core"; -import React, { useState } from "react"; -import { HiMenu } from "react-icons/hi"; -import { FcDocument, FcFolder, FcImageFile } from "react-icons/fc"; -import { BsDownload, BsListCheck } from "react-icons/bs"; +import { keyWibu, LayoutDrawer, LayoutModalViewFile, LayoutNavbarNew, TEMA, } from "@/module/_global"; +import LayoutModal from "@/module/_global/layout/layout_modal"; +import { funGetDivisionById } from "@/module/division_new"; +import { useHookstate } from "@hookstate/core"; +import { ActionIcon, Box, Breadcrumbs, Button, Checkbox, Divider, Flex, Grid, Group, Indicator, Menu, Modal, rem, SimpleGrid, Skeleton, Text, TextInput } from "@mantine/core"; +import { useMediaQuery, useShallowEffect } from "@mantine/hooks"; +import { useParams, useRouter, useSearchParams } from "next/navigation"; +import { useState } from "react"; +import toast from "react-hot-toast"; import { AiOutlineDelete } from "react-icons/ai"; +import { BsDownload, BsListCheck } from "react-icons/bs"; import { CgRename } from "react-icons/cg"; +import { FaShare } from "react-icons/fa6"; +import { FcDocument, FcFolder, FcImageFile } from "react-icons/fc"; +import { GoChevronRight } from "react-icons/go"; +import { HiMenu } from "react-icons/hi"; import { LuShare2 } from "react-icons/lu"; import { MdClose, MdOutlineMoreHoriz } from "react-icons/md"; -import LayoutModal from "@/module/_global/layout/layout_modal"; -import toast from "react-hot-toast"; -import { useParams, useRouter, useSearchParams } from "next/navigation"; +import { RiListCheck } from "react-icons/ri"; +import { funDeleteDocument, funGetAllDocument, funRenameDocument, } from "../lib/api_document"; +import { IDataDocument, IJalurItem } from "../lib/type_document"; +import { globalRefreshDocument } from "../lib/val_document"; import DrawerMenuDocumentDivision from "./drawer_menu_document_division"; import DrawerMore from "./drawer_more"; -import { funGetDivisionById } from "@/module/division_new"; -import { useMediaQuery, useShallowEffect } from "@mantine/hooks"; -import { - funDeleteDocument, - funGetAllDocument, - funRenameDocument, -} from "../lib/api_document"; -import { IDataDocument, IJalurItem } from "../lib/type_document"; -import { useHookstate } from "@hookstate/core"; -import { globalRefreshDocument } from "../lib/val_document"; -import { RiListCheck } from "react-icons/ri"; -import { GoChevronRight } from "react-icons/go"; import DrawerShareDocument from "./drawer_share_document"; -import { FaShare } from "react-icons/fa6"; +import { useWibuRealtime } from "wibu-realtime"; export default function NavbarDocumentDivision() { const router = useRouter(); @@ -80,6 +52,10 @@ export default function NavbarDocumentDivision() { const isMobile2 = useMediaQuery("(max-width: 496px)"); const tema = useHookstate(TEMA); const [loading, setLoading] = useState(true); + const [dataRealTime, setDataRealtime] = useWibuRealtime({ + WIBU_REALTIME_TOKEN: keyWibu, + project: "sdm" + }) const [bodyRename, setBodyRename] = useState({ id: "", name: "", @@ -166,7 +142,11 @@ export default function NavbarDocumentDivision() { try { const respon = await funDeleteDocument(selectedFiles); if (respon.success) { - getOneData(); + getOneData(false); + setDataRealtime([{ + category: "division-document", + id: path, + }]) } else { toast.error(respon.message); } @@ -185,7 +165,11 @@ export default function NavbarDocumentDivision() { try { const res = await funRenameDocument(bodyRename); if (res.success) { - getOneData(); + setDataRealtime([{ + category: "division-document", + id: path, + }]) + getOneData(false); } else { toast.error(res.message); } @@ -199,21 +183,25 @@ export default function NavbarDocumentDivision() { setRename(false); } - async function getOneData() { + useShallowEffect(() => { + if (dataRealTime && dataRealTime.some((i: any) => i.category == 'division-document' && i.id == path)) { + getOneData(false) + } + }, [dataRealTime]) + + async function getOneData(loading: boolean) { try { - setLoading(true); + setLoading(loading); const respon = await funGetAllDocument( "?division=" + param.id + "&path=" + path ); if (respon.success) { setDataDocument(respon.data); setDataJalur(respon.jalur); - setLoading(false); } else { toast.error(respon.message); setDataDocument([]); setDataJalur([]); - setLoading(false); } const res = await funGetDivisionById(param.id); if (res.success) { @@ -242,7 +230,7 @@ export default function NavbarDocumentDivision() { }, [selectedFiles]); useShallowEffect(() => { - getOneData(); + getOneData(true); resetRefresh(); }, [param.id, path, refresh.get()]);