diff --git a/app/(application)/(user)/notifications/index.tsx b/app/(application)/(user)/notifications/index.tsx index b10ee39..2e2c57b 100644 --- a/app/(application)/(user)/notifications/index.tsx +++ b/app/(application)/(user)/notifications/index.tsx @@ -1,9 +1,11 @@ -import ScreenNotification from "@/screens/Notification/ScreenNotification"; +import ScreenNotification from "@/screens/Notification/ScreenNotification_V2"; +import ScreenNotification_V1 from "@/screens/Notification/ScreenNotification_V1"; export default function Notification() { return ( <> + {/* */} ); } diff --git a/app/(application)/admin/notification/index.tsx b/app/(application)/admin/notification/index.tsx index 9875bd5..cd76188 100644 --- a/app/(application)/admin/notification/index.tsx +++ b/app/(application)/admin/notification/index.tsx @@ -1,213 +1,10 @@ -import { - AlertDefaultSystem, - BackButton, - BaseBox, - DrawerCustom, - MenuDrawerDynamicGrid, - NewWrapper, - ScrollableCustom, - StackCustom, - TextCustom, -} from "@/components"; -import { IconPlus } from "@/components/_Icon"; -import { IconDot } from "@/components/_Icon/IconComponent"; -import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent"; -import NoDataText from "@/components/_ShareComponent/NoDataText"; -import { AccentColor, MainColor } from "@/constants/color-palet"; -import { ICON_SIZE_SMALL } from "@/constants/constans-value"; -import { useAuth } from "@/hooks/use-auth"; -import { useNotificationStore } from "@/hooks/use-notification-store"; -import { apiGetNotificationsById } from "@/service/api-notifications"; -import { listOfcategoriesAppNotification } from "@/types/type-notification-category"; -import { formatChatTime } from "@/utils/formatChatTime"; -import { Ionicons } from "@expo/vector-icons"; -import { router, Stack, useFocusEffect } from "expo-router"; -import _ from "lodash"; -import { useCallback, useState } from "react"; -import { RefreshControl, View } from "react-native"; - -const selectedCategory = (value: string) => { - const category = listOfcategoriesAppNotification.find( - (c) => c.value === value - ); - return category?.label; -}; - -const BoxNotification = ({ - data, - activeCategory, -}: { - data: any; - activeCategory: string | null; -}) => { - const { markAsRead } = useNotificationStore(); - return ( - <> - { - console.log( - "Notification >", - selectedCategory(activeCategory as string) - ); - router.push(data.deepLink); - markAsRead(data.id); - }} - > - - - {data.title} - - - {data.pesan} - - - {formatChatTime(data.createdAt)} - - - - - ); -}; +import Admin_ScreenNotification from "@/screens/Admin/Notification-Admin/ScreenNotificationAdmin"; +import Admin_ScreenNotification2 from "@/screens/Admin/Notification-Admin/ScreenNotificationAdmin2"; export default function AdminNotification() { - const { user } = useAuth(); - const [activeCategory, setActiveCategory] = useState("event"); - const [listData, setListData] = useState([]); - const [refreshing, setRefreshing] = useState(false); - const [loading, setLoading] = useState(false); - const [openDrawer, setOpenDrawer] = useState(false); - - const { markAsReadAll } = useNotificationStore(); - - const handlePress = (item: any) => { - setActiveCategory(item.value); - // tambahkan logika lain seperti filter dsb. - }; - - useFocusEffect( - useCallback(() => { - fecthData(); - }, [activeCategory]) - ); - - const fecthData = async () => { - try { - setLoading(true); - const response = await apiGetNotificationsById({ - id: user?.id as any, - category: activeCategory as any, - }); - - if (response.success) { - setListData(response.data); - } else { - setListData([]); - } - } catch (error) { - console.log("Error Notification", error); - } finally { - setLoading(false); - } - }; - - const onRefresh = () => { - setRefreshing(true); - fecthData(); - setRefreshing(false); - }; - return ( <> - , - headerRight: () => ( - setOpenDrawer(true)} - /> - ), - }} - /> - - ({ - id: i, - label: e.label, - value: e.value, - }))} - onButtonPress={handlePress} - activeId={activeCategory as string} - /> - } - refreshControl={ - - } - > - {loading ? ( - - ) : _.isEmpty(listData) ? ( - - ) : ( - listData.map((e, i) => ( - - - - )) - )} - - - setOpenDrawer(false)} - height={"auto"} - > - - ), - path: "", - }, - ]} - onPressItem={(item: any) => { - console.log("Item", item.value); - if (item.value === "read-all") { - AlertDefaultSystem({ - title: "Tandai Semua Dibaca", - message: - "Apakah Anda yakin ingin menandai semua notifikasi dibaca?", - textLeft: "Batal", - textRight: "Ya", - onPressRight: () => { - markAsReadAll(user?.id as any); - const data = _.cloneDeep(listData); - data.forEach((e) => { - e.isRead = true; - }); - setListData(data); - onRefresh(); - setOpenDrawer(false); - }, - }); - } - }} - /> - + ); } diff --git a/docs/prompt-for-qwen-code.md b/docs/prompt-for-qwen-code.md index 6cca10e..d3d30d8 100644 --- a/docs/prompt-for-qwen-code.md +++ b/docs/prompt-for-qwen-code.md @@ -1,8 +1,8 @@ -File utama: screens/Job/ScreenArchive2.tsx -Fun fecth: apiJobGetByStatus -File fetch: service/api-client/api-job.ts +File utama: screens/Admin/Notification-Admin/ScreenNotificationAdmin2.tsx +Fun fecth: apiGetNotificationsById +File fetch: service/api-notifications.ts File komponen wrapper: components/_ShareComponent/NewWrapper.tsx Terapkan pagination pada file "File utama" diff --git a/screens/Admin/Notification-Admin/ScreenNotificationAdmin.tsx b/screens/Admin/Notification-Admin/ScreenNotificationAdmin.tsx new file mode 100644 index 0000000..5a36598 --- /dev/null +++ b/screens/Admin/Notification-Admin/ScreenNotificationAdmin.tsx @@ -0,0 +1,213 @@ +import { + AlertDefaultSystem, + BackButton, + BaseBox, + DrawerCustom, + MenuDrawerDynamicGrid, + NewWrapper, + ScrollableCustom, + StackCustom, + TextCustom, +} from "@/components"; +import { IconPlus } from "@/components/_Icon"; +import { IconDot } from "@/components/_Icon/IconComponent"; +import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent"; +import NoDataText from "@/components/_ShareComponent/NoDataText"; +import { AccentColor, MainColor } from "@/constants/color-palet"; +import { ICON_SIZE_SMALL } from "@/constants/constans-value"; +import { useAuth } from "@/hooks/use-auth"; +import { useNotificationStore } from "@/hooks/use-notification-store"; +import { apiGetNotificationsById } from "@/service/api-notifications"; +import { listOfcategoriesAppNotification } from "@/types/type-notification-category"; +import { formatChatTime } from "@/utils/formatChatTime"; +import { Ionicons } from "@expo/vector-icons"; +import { router, Stack, useFocusEffect } from "expo-router"; +import _ from "lodash"; +import { useCallback, useState } from "react"; +import { RefreshControl, View } from "react-native"; + +const selectedCategory = (value: string) => { + const category = listOfcategoriesAppNotification.find( + (c) => c.value === value + ); + return category?.label; +}; + +const BoxNotification = ({ + data, + activeCategory, +}: { + data: any; + activeCategory: string | null; +}) => { + const { markAsRead } = useNotificationStore(); + return ( + <> + { + console.log( + "Notification >", + selectedCategory(activeCategory as string) + ); + router.push(data.deepLink); + markAsRead(data.id); + }} + > + + + {data.title} + + + {data.pesan} + + + {formatChatTime(data.createdAt)} + + + + + ); +}; + +export default function Admin_ScreenNotification() { + const { user } = useAuth(); + const [activeCategory, setActiveCategory] = useState("event"); + const [listData, setListData] = useState([]); + const [refreshing, setRefreshing] = useState(false); + const [loading, setLoading] = useState(false); + const [openDrawer, setOpenDrawer] = useState(false); + + const { markAsReadAll } = useNotificationStore(); + + const handlePress = (item: any) => { + setActiveCategory(item.value); + // tambahkan logika lain seperti filter dsb. + }; + + useFocusEffect( + useCallback(() => { + fecthData(); + }, [activeCategory]) + ); + + const fecthData = async () => { + try { + setLoading(true); + const response = await apiGetNotificationsById({ + id: user?.id as any, + category: activeCategory as any, + }); + + if (response.success) { + setListData(response.data); + } else { + setListData([]); + } + } catch (error) { + console.log("Error Notification", error); + } finally { + setLoading(false); + } + }; + + const onRefresh = () => { + setRefreshing(true); + fecthData(); + setRefreshing(false); + }; + + return ( + <> + , + headerRight: () => ( + setOpenDrawer(true)} + /> + ), + }} + /> + + ({ + id: i, + label: e.label, + value: e.value, + }))} + onButtonPress={handlePress} + activeId={activeCategory as string} + /> + } + refreshControl={ + + } + > + {loading ? ( + + ) : _.isEmpty(listData) ? ( + + ) : ( + listData.map((e, i) => ( + + + + )) + )} + + + setOpenDrawer(false)} + height={"auto"} + > + + ), + path: "", + }, + ]} + onPressItem={(item: any) => { + console.log("Item", item.value); + if (item.value === "read-all") { + AlertDefaultSystem({ + title: "Tandai Semua Dibaca", + message: + "Apakah Anda yakin ingin menandai semua notifikasi dibaca?", + textLeft: "Batal", + textRight: "Ya", + onPressRight: () => { + markAsReadAll(user?.id as any); + const data = _.cloneDeep(listData); + data.forEach((e) => { + e.isRead = true; + }); + setListData(data); + onRefresh(); + setOpenDrawer(false); + }, + }); + } + }} + /> + + + ); +} diff --git a/screens/Admin/Notification-Admin/ScreenNotificationAdmin2.tsx b/screens/Admin/Notification-Admin/ScreenNotificationAdmin2.tsx new file mode 100644 index 0000000..26816b5 --- /dev/null +++ b/screens/Admin/Notification-Admin/ScreenNotificationAdmin2.tsx @@ -0,0 +1,222 @@ +import { + AlertDefaultSystem, + BackButton, + BaseBox, + DrawerCustom, + MenuDrawerDynamicGrid, + NewWrapper, + ScrollableCustom, + StackCustom, + TextCustom, +} from "@/components"; +import { IconPlus } from "@/components/_Icon"; +import { IconDot } from "@/components/_Icon/IconComponent"; +import { AccentColor, MainColor } from "@/constants/color-palet"; +import { ICON_SIZE_SMALL } from "@/constants/constans-value"; +import { createPaginationComponents } from "@/helpers/paginationHelpers"; +import { useAuth } from "@/hooks/use-auth"; +import { useNotificationStore } from "@/hooks/use-notification-store"; +import { usePagination } from "@/hooks/use-pagination"; +import { apiGetNotificationsById } from "@/service/api-notifications"; +import { listOfcategoriesAppNotification } from "@/types/type-notification-category"; +import { formatChatTime } from "@/utils/formatChatTime"; +import { Ionicons } from "@expo/vector-icons"; +import { router, Stack, useFocusEffect } from "expo-router"; +import _ from "lodash"; +import { useState } from "react"; +import { RefreshControl, View } from "react-native"; + +const PAGE_SIZE = 10; + +const selectedCategory = (value: string) => { + const category = listOfcategoriesAppNotification.find( + (c) => c.value === value, + ); + return category?.label; +}; + +const BoxNotification = ({ + data, + activeCategory, + setListData, +}: { + data: any; + activeCategory: string | null; + setListData: (data: any) => void; +}) => { + const { markAsRead } = useNotificationStore(); + return ( + <> + { + console.log( + "Notification >", + selectedCategory(activeCategory as string), + ); + router.push(data.deepLink); + markAsRead(data.id); + setListData((prev: any) => + prev.map((item: any) => + item.id === data.id ? { ...item, isRead: true } : item, + ), + ); + }} + > + + + {data.title} + + + {data.pesan} + + + {formatChatTime(data.createdAt)} + + + + + ); +}; + +export default function Admin_ScreenNotification2() { + const { user } = useAuth(); + const [activeCategory, setActiveCategory] = useState("event"); + const [openDrawer, setOpenDrawer] = useState(false); + + const { markAsReadAll } = useNotificationStore(); + + // Setup pagination + const pagination = usePagination({ + fetchFunction: async (page) => { + if (!user?.id) return { data: [] }; + + return await apiGetNotificationsById({ + id: user?.id as any, + category: activeCategory as any, + page: String(page), + }); + }, + pageSize: PAGE_SIZE, + dependencies: [user?.id, activeCategory], + onError: (error) => + console.error("[ERROR] Fetch admin notifications:", error), + }); + + // Generate komponen + const { ListEmptyComponent, ListFooterComponent } = + createPaginationComponents({ + loading: pagination.loading, + refreshing: pagination.refreshing, + listData: pagination.listData, + emptyMessage: "Belum ada notifikasi", + skeletonCount: 5, + skeletonHeight: 100, + }); + + // Render item notification + const renderNotificationItem = ({ item }: { item: any }) => ( + + + + ); + + const handlePress = (item: any) => { + setActiveCategory(item.value); + // Reset pagination saat kategori berubah + pagination.reset(); + }; + + return ( + <> + , + headerRight: () => ( + setOpenDrawer(true)} + /> + ), + }} + /> + + ({ + id: i, + label: e.label, + value: e.value, + }))} + onButtonPress={handlePress} + activeId={activeCategory as string} + /> + } + listData={pagination.listData} + renderItem={renderNotificationItem} + refreshControl={ + + } + onEndReached={pagination.loadMore} + ListEmptyComponent={ListEmptyComponent} + ListFooterComponent={ListFooterComponent} + /> + + setOpenDrawer(false)} + height={"auto"} + > + + ), + path: "", + }, + ]} + onPressItem={(item: any) => { + console.log("Item", item.value); + if (item.value === "read-all") { + AlertDefaultSystem({ + title: "Tandai Semua Dibaca", + message: + "Apakah Anda yakin ingin menandai semua notifikasi dibaca?", + textLeft: "Batal", + textRight: "Ya", + onPressRight: () => { + markAsReadAll(user?.id as any); + const data = _.cloneDeep(pagination.listData); + data.forEach((e) => { + e.isRead = true; + }); + pagination.setListData(data); + pagination.onRefresh(); + setOpenDrawer(false); + }, + }); + } + }} + /> + + + ); +} diff --git a/screens/Job/MainViewStatus2.tsx b/screens/Job/MainViewStatus2.tsx index 13385e3..c53724a 100644 --- a/screens/Job/MainViewStatus2.tsx +++ b/screens/Job/MainViewStatus2.tsx @@ -1,22 +1,16 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import { - BaseBox, - ScrollableCustom, - TextCustom, - ViewWrapper, -} from "@/components"; +import { BaseBox, ScrollableCustom, TextCustom } from "@/components"; +import NewWrapper from "@/components/_ShareComponent/NewWrapper"; import { MainColor } from "@/constants/color-palet"; +import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value"; import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { useAuth } from "@/hooks/use-auth"; import { usePagination } from "@/hooks/use-pagination"; import { dummyMasterStatus } from "@/lib/dummy-data/_master/status"; import { apiJobGetByStatus } from "@/service/api-client/api-job"; import { useFocusEffect, useLocalSearchParams } from "expo-router"; -import _ from "lodash"; -import { useState } from "react"; +import { useCallback, useState } from "react"; import { RefreshControl, View } from "react-native"; -import NewWrapper from "@/components/_ShareComponent/NewWrapper"; -import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value"; export default function Job_MainViewStatus2() { const { user } = useAuth(); @@ -24,7 +18,7 @@ export default function Job_MainViewStatus2() { console.log("STATUS", status); const [activeCategory, setActiveCategory] = useState( - status || "publish" + status || "publish", ); // Setup pagination @@ -44,14 +38,15 @@ export default function Job_MainViewStatus2() { }); // Generate komponen - const { ListEmptyComponent, ListFooterComponent } = createPaginationComponents({ - loading: pagination.loading, - refreshing: pagination.refreshing, - listData: pagination.listData, - emptyMessage: `Tidak ada data ${activeCategory}`, - skeletonCount: PAGINATION_DEFAULT_TAKE, - skeletonHeight: 100, - }); + const { ListEmptyComponent, ListFooterComponent } = + createPaginationComponents({ + loading: pagination.loading, + refreshing: pagination.refreshing, + listData: pagination.listData, + emptyMessage: `Tidak ada data ${activeCategory}`, + skeletonCount: PAGINATION_DEFAULT_TAKE, + skeletonHeight: 100, + }); // Render item job const renderJobItem = ({ item }: { item: any }) => ( @@ -67,6 +62,14 @@ export default function Job_MainViewStatus2() { ); + // useFocusEffect( + // useCallback(() => { + // // Reset and load first page when category changes + // pagination.reset(); + // // pagination.onRefresh(); + // }, [activeCategory]), + // ); + const handlePress = (item: any) => { setActiveCategory(item.value); // Reset pagination saat kategori berubah @@ -87,11 +90,7 @@ export default function Job_MainViewStatus2() { return ( - {scrollComponent} - - } + headerComponent={{scrollComponent}} listData={pagination.listData} renderItem={renderJobItem} refreshControl={ diff --git a/screens/Notification/ScreenNotification_V1.tsx b/screens/Notification/ScreenNotification_V1.tsx new file mode 100644 index 0000000..6b11ec6 --- /dev/null +++ b/screens/Notification/ScreenNotification_V1.tsx @@ -0,0 +1,321 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import { + AlertDefaultSystem, + BackButton, + BaseBox, + DrawerCustom, + LoaderCustom, + MenuDrawerDynamicGrid, + NewWrapper, + ScrollableCustom, + StackCustom, + TextCustom, +} from "@/components"; +import { IconDot } from "@/components/_Icon/IconComponent"; +import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent"; +import NoDataText from "@/components/_ShareComponent/NoDataText"; +import { AccentColor, MainColor } from "@/constants/color-palet"; +import { ICON_SIZE_SMALL } from "@/constants/constans-value"; +import { useAuth } from "@/hooks/use-auth"; +import { useNotificationStore } from "@/hooks/use-notification-store"; +import { apiGetNotificationsById } from "@/service/api-notifications"; +import { listOfcategoriesAppNotification } from "@/types/type-notification-category"; +import { formatChatTime } from "@/utils/formatChatTime"; +import { Ionicons } from "@expo/vector-icons"; +import { + router, + Stack, + useFocusEffect, + useLocalSearchParams, +} from "expo-router"; +import _ from "lodash"; +import { useCallback, useEffect, useState } from "react"; +import { RefreshControl, View } from "react-native"; + +const selectedCategory = (value: string) => { + const category = listOfcategoriesAppNotification.find( + (c) => c.value === value, + ); + return category?.label; +}; + +const fixPath = ({ + deepLink, + categoryApp, +}: { + deepLink: string; + categoryApp: string; +}) => { + if (categoryApp === "OTHER") { + return deepLink; + } + + const separator = deepLink.includes("?") ? "&" : "?"; + + const fixedPath = `${deepLink}${separator}from=notifications&category=${_.lowerCase( + categoryApp, + )}`; + + console.log("Fix Path", fixedPath); + + return fixedPath; +}; + +const BoxNotification = ({ + data, + activeCategory, + setListData, +}: { + data: any; + activeCategory: string | null; + setListData: (data: any) => void; +}) => { + // console.log("DATA NOTIFICATION", JSON.stringify(data, null, 2)); + const { markAsRead } = useNotificationStore(); + return ( + <> + { + // console.log( + // "Notification >", + // selectedCategory(activeCategory as string) + // ); + const newPath = fixPath({ + deepLink: data.deepLink, + categoryApp: data.kategoriApp, + }); + + router.navigate(newPath as any); + selectedCategory(activeCategory as string); + + if (!data.isRead) { + markAsRead(data.id); + const updatedData = { + ...data, + isRead: true, + }; + + console.log("Updated Data", updatedData); + setListData((prev: any) => + prev.map((item: any) => + item.id === data.id ? updatedData : item, + ), + ); + } + }} + > + + + {data.title} + + + {data.pesan} + + + {formatChatTime(data.createdAt)} + + + + + ); +}; + +export default function ScreenNotification_V1() { + const { user } = useAuth(); + const { category } = useLocalSearchParams<{ category?: string }>(); + const [activeCategory, setActiveCategory] = useState( + category || "event", + ); + const [listData, setListData] = useState([]); + const [refreshing, setRefreshing] = useState(false); + const [loading, setLoading] = useState(false); + const [loadingMore, setLoadingMore] = useState(false); + const [page, setPage] = useState(1); + const [hasMore, setHasMore] = useState(true); + const [openDrawer, setOpenDrawer] = useState(false); + + const { markAsReadAll } = useNotificationStore(); + + const handlePress = (item: any) => { + setActiveCategory(item.value); + // Reset pagination saat kategori berubah + setListData([]); + setPage(1); + setHasMore(true); + }; + + // useFocusEffect( + // useCallback(() => { + // fecthData(1, true); + // }, [activeCategory]) + // ); + + useEffect(() => { + fecthData(1, true); + }, [activeCategory]); + + const fecthData = async (pageNum: number, clear: boolean = false) => { + if (pageNum === 1 && !clear) return; // Hindari duplicate call untuk page 1 + + try { + if (pageNum === 1) { + setLoading(true); + } else { + setLoadingMore(true); + } + + const response = await apiGetNotificationsById({ + id: user?.id as any, + category: activeCategory as any, + page: String(pageNum), + }); + + if (response.success) { + if (clear || pageNum === 1) { + setListData(response.data); + } else { + setListData((prev) => [...prev, ...response.data]); + } + + // Jika data yang dikembalikan kurang dari ukuran halaman, maka tidak ada halaman berikutnya + setHasMore(response.data.length >= 10); // Asumsikan ukuran halaman 10 + } else { + if (pageNum === 1) { + setListData([]); + } + } + } catch (error) { + console.log("Error Notification", error); + if (pageNum === 1) { + setListData([]); + } + } finally { + if (pageNum === 1) { + setLoading(false); + } else { + setLoadingMore(false); + } + } + }; + + const onRefresh = async () => { + setRefreshing(true); + await fecthData(1, true); + setRefreshing(false); + }; + + const loadMore = () => { + if (!loadingMore && hasMore) { + const nextPage = page + 1; + setPage(nextPage); + fecthData(nextPage, false); + } + }; + + return ( + <> + , + headerRight: () => ( + setOpenDrawer(true)} + /> + ), + }} + /> + + ({ + id: i, + label: e.label, + value: e.value, + }))} + onButtonPress={handlePress} + activeId={activeCategory as string} + /> + } + listData={listData} + renderItem={({ item }) => ( + + + + )} + refreshControl={ + + } + onEndReached={loadMore} + // onEndReachedThreshold={0.1} + ListEmptyComponent={ + loading ? ( + + ) : ( + + ) + } + ListFooterComponent={ + loadingMore ? ( + + + + ) : null + } + /> + + setOpenDrawer(false)} + height={"auto"} + > + + ), + path: "", + }, + ]} + onPressItem={(item: any) => { + console.log("Item", item.value); + if (item.value === "read-all") { + AlertDefaultSystem({ + title: "Tandai Semua Dibaca", + message: + "Apakah Anda yakin ingin menandai semua notifikasi dibaca?", + textLeft: "Batal", + textRight: "Ya", + onPressRight: () => { + markAsReadAll(user?.id as any); + const data = _.cloneDeep(listData); + data.forEach((e) => { + e.isRead = true; + }); + setListData(data); + onRefresh(); + setOpenDrawer(false); + }, + }); + } + }} + /> + + + ); +} diff --git a/screens/Notification/ScreenNotification.tsx b/screens/Notification/ScreenNotification_V2.tsx similarity index 79% rename from screens/Notification/ScreenNotification.tsx rename to screens/Notification/ScreenNotification_V2.tsx index e8dfcd7..f4f12cb 100644 --- a/screens/Notification/ScreenNotification.tsx +++ b/screens/Notification/ScreenNotification_V2.tsx @@ -11,26 +11,32 @@ import { TextCustom, } from "@/components"; import { IconDot } from "@/components/_Icon/IconComponent"; -import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent"; -import NoDataText from "@/components/_ShareComponent/NoDataText"; import { AccentColor, MainColor } from "@/constants/color-palet"; -import { ICON_SIZE_SMALL, PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value"; +import { + ICON_SIZE_SMALL, + PAGINATION_DEFAULT_TAKE, +} from "@/constants/constans-value"; +import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { useAuth } from "@/hooks/use-auth"; import { useNotificationStore } from "@/hooks/use-notification-store"; import { usePagination } from "@/hooks/use-pagination"; -import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { apiGetNotificationsById } from "@/service/api-notifications"; import { listOfcategoriesAppNotification } from "@/types/type-notification-category"; import { formatChatTime } from "@/utils/formatChatTime"; import { Ionicons } from "@expo/vector-icons"; -import { router, Stack, useFocusEffect, useLocalSearchParams } from "expo-router"; +import { + router, + Stack, + useFocusEffect, + useLocalSearchParams, +} from "expo-router"; import _ from "lodash"; import { useCallback, useState } from "react"; import { RefreshControl, View } from "react-native"; const selectedCategory = (value: string) => { const category = listOfcategoriesAppNotification.find( - (c) => c.value === value + (c) => c.value === value, ); return category?.label; }; @@ -49,7 +55,7 @@ const fixPath = ({ const separator = deepLink.includes("?") ? "&" : "?"; const fixedPath = `${deepLink}${separator}from=notifications&category=${_.lowerCase( - categoryApp + categoryApp, )}`; console.log("Fix Path", fixedPath); @@ -60,21 +66,18 @@ const fixPath = ({ const BoxNotification = ({ data, activeCategory, + setListData, }: { data: any; activeCategory: string | null; + setListData: (data: any) => void; }) => { - // console.log("DATA NOTIFICATION", JSON.stringify(data, null, 2)); const { markAsRead } = useNotificationStore(); return ( <> { - // console.log( - // "Notification >", - // selectedCategory(activeCategory as string) - // ); const newPath = fixPath({ deepLink: data.deepLink, categoryApp: data.kategoriApp, @@ -85,6 +88,11 @@ const BoxNotification = ({ if (!data.isRead) { markAsRead(data.id); + setListData((prev: any) => + prev.map((item: any) => + item.id === data.id ? { ...item, isRead: true } : item, + ), + ); } }} > @@ -108,7 +116,7 @@ export default function ScreenNotification() { const { user } = useAuth(); const { category } = useLocalSearchParams<{ category?: string }>(); const [activeCategory, setActiveCategory] = useState( - category || "event" + category || "event", ); const [openDrawer, setOpenDrawer] = useState(false); @@ -117,6 +125,8 @@ export default function ScreenNotification() { // Initialize pagination for notifications const pagination = usePagination({ fetchFunction: async (page) => { + if (!user?.id) return { data: [] }; + return await apiGetNotificationsById({ id: user?.id as string, category: activeCategory as any, @@ -127,20 +137,19 @@ export default function ScreenNotification() { dependencies: [activeCategory], }); - useFocusEffect( - useCallback(() => { - // Reset and load first page when category changes - pagination.reset(); - pagination.onRefresh(); - }, [activeCategory]) - ); + // useFocusEffect( + // useCallback(() => { + // // Reset and load first page when category changes + // pagination.reset(); + // pagination.onRefresh(); + // }, [activeCategory]), + // ); const handlePress = (item: any) => { - console.log("ITEM", item.value); setActiveCategory(item.value); // Reset and load first page when category changes - pagination.reset(); - pagination.onRefresh(); + // pagination.reset(); + // pagination.onRefresh(); }; // Render individual notification item @@ -149,24 +158,26 @@ export default function ScreenNotification() { ); // Generate pagination components using helper - const { ListEmptyComponent, ListFooterComponent } = createPaginationComponents({ - loading: pagination.loading, - refreshing: pagination.refreshing, - listData: pagination.listData, - isInitialLoad: pagination.isInitialLoad, - emptyMessage: "Belum ada notifikasi", - skeletonCount: 5, - skeletonHeight: 100, - }); + const { ListEmptyComponent, ListFooterComponent } = + createPaginationComponents({ + loading: pagination.loading, + refreshing: pagination.refreshing, + listData: pagination.listData, + isInitialLoad: pagination.isInitialLoad, + emptyMessage: "Belum ada notifikasi", + skeletonCount: 5, + skeletonHeight: 100, + }); return ( <> - , @@ -180,6 +191,7 @@ export default function ScreenNotification() { /> ({ @@ -225,7 +237,7 @@ export default function ScreenNotification() { }, ]} onPressItem={(item: any) => { - console.log("Item", item.value); + // console.log("Item", item.value); if (item.value === "read-all") { AlertDefaultSystem({ title: "Tandai Semua Dibaca", @@ -234,9 +246,13 @@ export default function ScreenNotification() { textLeft: "Batal", textRight: "Ya", onPressRight: () => { - markAsReadAll(user?.id as any); // Reset and refresh data after marking all as read - pagination.reset(); + markAsReadAll(user?.id as any); + const data = _.cloneDeep(pagination.listData); + data.forEach((e) => { + e.isRead = true; + }); + pagination.setListData(data); pagination.onRefresh(); setOpenDrawer(false); },