From 145ad73616c21c93266aeee78c8f559d6cd61321 Mon Sep 17 00:00:00 2001 From: bagasbanuna Date: Thu, 8 Jan 2026 10:12:53 +0800 Subject: [PATCH] Fix job notifikasi ### No Issue --- app/(application)/(user)/_layout.tsx | 3 +- .../(user)/job/(tabs)/_layout.tsx | 90 +++++++++++++------ .../(user)/job/(tabs)/status.tsx | 51 ++++++----- .../(user)/job/[id]/[status]/detail.tsx | 2 +- app/(application)/(user)/job/create.tsx | 2 +- .../(user)/notifications/index.tsx | 42 +++++++-- .../admin/job/[id]/[status]/reject-input.tsx | 11 ++- .../admin/notification/index.tsx | 26 ++++-- components/Button/BackButton.tsx | 4 +- screens/Admin/Job/funUpdateStatus.ts | 2 +- 10 files changed, 163 insertions(+), 70 deletions(-) diff --git a/app/(application)/(user)/_layout.tsx b/app/(application)/(user)/_layout.tsx index f7a1365..73acf8c 100644 --- a/app/(application)/(user)/_layout.tsx +++ b/app/(application)/(user)/_layout.tsx @@ -519,7 +519,8 @@ export default function UserLayout() { name="job/(tabs)" options={{ title: "Job Vacancy", - headerLeft: () => , + // headerLeft: () => , + // Note: headerLeft di pindahkan ke Tabs Layout }} /> (); + + // Atur header secara dinamis + useLayoutEffect(() => { + navigation.setOptions({ + headerLeft: () => ( + { + if (from === "notifications") { + router.replace(`/notifications?category=${category}`); + } else { + if (from) { + router.replace(`/${from}` as any); + } else { + router.back(); + } + } + }} + /> + ), + }); + }, [from, router, navigation]); + return ( - - , - }} - /> - , - }} - /> - ( - - ), - }} - /> - + <> + + , + }} + /> + , + }} + /> + ( + + ), + }} + /> + + ); } diff --git a/app/(application)/(user)/job/(tabs)/status.tsx b/app/(application)/(user)/job/(tabs)/status.tsx index 4c1f004..87e0f22 100644 --- a/app/(application)/(user)/job/(tabs)/status.tsx +++ b/app/(application)/(user)/job/(tabs)/status.tsx @@ -9,14 +9,17 @@ import { import { useAuth } from "@/hooks/use-auth"; import { dummyMasterStatus } from "@/lib/dummy-data/_master/status"; import { apiJobGetByStatus } from "@/service/api-client/api-job"; -import { useFocusEffect } from "expo-router"; +import { useFocusEffect, useLocalSearchParams } from "expo-router"; import _ from "lodash"; import { useCallback, useState } from "react"; export default function JobStatus() { const { user } = useAuth(); + const { status } = useLocalSearchParams<{ status?: string }>(); + console.log("STATUS", status); + const [activeCategory, setActiveCategory] = useState( - "publish" + status || "publish" ); const [listData, setListData] = useState([]); const [isLoadList, setIsLoadList] = useState(false); @@ -60,25 +63,29 @@ export default function JobStatus() { ); return ( - - {isLoadList ? ( - - ) : _.isEmpty(listData) ? ( - Tidak ada data {activeCategory} - ) : ( - listData.map((e, i) => ( - - - {e?.title} - - - )) - )} - + <> + + {isLoadList ? ( + + ) : _.isEmpty(listData) ? ( + + Tidak ada data {activeCategory} + + ) : ( + listData.map((e, i) => ( + + + {e?.title} + + + )) + )} + + ); } diff --git a/app/(application)/(user)/job/[id]/[status]/detail.tsx b/app/(application)/(user)/job/[id]/[status]/detail.tsx index c6b9529..4c1b216 100644 --- a/app/(application)/(user)/job/[id]/[status]/detail.tsx +++ b/app/(application)/(user)/job/[id]/[status]/detail.tsx @@ -74,7 +74,7 @@ export default function JobDetailStatus() { {data && data?.catatan && - (status === "draft" || status === "rejected") && ( + (status === "draft" || status === "reject") && ( )} diff --git a/app/(application)/(user)/job/create.tsx b/app/(application)/(user)/job/create.tsx index 4009c10..1879e2f 100644 --- a/app/(application)/(user)/job/create.tsx +++ b/app/(application)/(user)/job/create.tsx @@ -19,7 +19,7 @@ import { useState } from "react"; import Toast from "react-native-toast-message"; export default function JobCreate() { - const nextUrl = "/(application)/(user)/job/(tabs)/status"; + const nextUrl = "/(application)/(user)/job/(tabs)/status?status=review"; const { user } = useAuth(); const [isLoading, setIsLoading] = useState(false); const [image, setImage] = useState(null); diff --git a/app/(application)/(user)/notifications/index.tsx b/app/(application)/(user)/notifications/index.tsx index 313f952..3eba978 100644 --- a/app/(application)/(user)/notifications/index.tsx +++ b/app/(application)/(user)/notifications/index.tsx @@ -13,7 +13,7 @@ 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 { router, useFocusEffect } from "expo-router"; +import { router, useFocusEffect, useLocalSearchParams } from "expo-router"; import _ from "lodash"; import { useCallback, useState } from "react"; import { RefreshControl, View } from "react-native"; @@ -25,6 +25,19 @@ const selectedCategory = (value: string) => { return category?.label; }; +const fixPath = ({ + deepLink, + categoryApp, +}: { + deepLink: string; + categoryApp: string; +}) => { + const fixPath = + deepLink + "&from=notifications&category=" + _.lowerCase(categoryApp); + + return fixPath; +}; + const BoxNotification = ({ data, activeCategory, @@ -32,18 +45,28 @@ const BoxNotification = ({ data: any; activeCategory: string | null; }) => { + // console.log("DATA NOTIFICATION", JSON.stringify(data, null, 2)); const { markAsRead } = useNotificationStore(); return ( <> { - console.log( - "Notification >", - selectedCategory(activeCategory as string) - ); - router.push(data.deepLink); - markAsRead(data.id); + // console.log( + // "Notification >", + // selectedCategory(activeCategory as string) + // ); + const newPath = fixPath({ + deepLink: data.deepLink, + categoryApp: data.kategoriApp, + }); + + router.replace(newPath as any); + selectedCategory(activeCategory as string); + + if (!data.isRead) { + markAsRead(data.id); + } }} > @@ -64,7 +87,10 @@ const BoxNotification = ({ export default function Notifications() { const { user } = useAuth(); - const [activeCategory, setActiveCategory] = useState("event"); + 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); diff --git a/app/(application)/admin/job/[id]/[status]/reject-input.tsx b/app/(application)/admin/job/[id]/[status]/reject-input.tsx index fbc8d56..d3b9766 100644 --- a/app/(application)/admin/job/[id]/[status]/reject-input.tsx +++ b/app/(application)/admin/job/[id]/[status]/reject-input.tsx @@ -15,7 +15,10 @@ import Toast from "react-native-toast-message"; export default function AdminJobRejectInput() { const { id, status } = useLocalSearchParams(); - const [data, setData] = useState(null); + const [data, setData] = useState({ + catatan: "", + senderId: "" + }); const [isLoading, setIsLoading] = useState(false); useFocusEffect( @@ -48,7 +51,7 @@ export default function AdminJobRejectInput() { const response = await funUpdateStatusJob({ id: id as string, changeStatus, - data: data, + data: data , }); if (!response.success) { @@ -102,8 +105,8 @@ export default function AdminJobRejectInput() { headerComponent={} > setData({ ...data, catatan: text })} placeholder="Masukan alasan" required showCount diff --git a/app/(application)/admin/notification/index.tsx b/app/(application)/admin/notification/index.tsx index 03ce45b..0ff1992 100644 --- a/app/(application)/admin/notification/index.tsx +++ b/app/(application)/admin/notification/index.tsx @@ -7,6 +7,8 @@ import { TextCustom, } from "@/components"; import { IconPlus } from "@/components/_Icon"; +import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent"; +import NoDataText from "@/components/_ShareComponent/NoDataText"; import { AccentColor, MainColor } from "@/constants/color-palet"; import { useAuth } from "@/hooks/use-auth"; import { useNotificationStore } from "@/hooks/use-notification-store"; @@ -14,6 +16,7 @@ import { apiGetNotificationsById } from "@/service/api-notifications"; import { listOfcategoriesAppNotification } from "@/types/type-notification-category"; import { formatChatTime } from "@/utils/formatChatTime"; import { router, Stack, useFocusEffect } from "expo-router"; +import _ from "lodash"; import { useCallback, useState } from "react"; import { RefreshControl, View } from "react-native"; @@ -66,6 +69,7 @@ export default function AdminNotification() { const [activeCategory, setActiveCategory] = useState("event"); const [listData, setListData] = useState([]); const [refreshing, setRefreshing] = useState(false); + const [loading, setLoading] = useState(false); const handlePress = (item: any) => { setActiveCategory(item.value); @@ -80,6 +84,7 @@ export default function AdminNotification() { const fecthData = async () => { try { + setLoading(true); const response = await apiGetNotificationsById({ id: user?.id as any, category: activeCategory as any, @@ -92,6 +97,8 @@ export default function AdminNotification() { } } catch (error) { console.log("Error Notification", error); + } finally { + setLoading(false); } }; @@ -132,11 +139,20 @@ export default function AdminNotification() { } > - {listData.map((e, i) => ( - - - - ))} + {loading ? ( + + ) : _.isEmpty(listData) ? ( + + ) : ( + listData.map((e, i) => ( + + + + )) + )} ); diff --git a/components/Button/BackButton.tsx b/components/Button/BackButton.tsx index 4bdd44d..9dba78a 100644 --- a/components/Button/BackButton.tsx +++ b/components/Button/BackButton.tsx @@ -12,10 +12,12 @@ const LeftButtonCustom = ({ path, icon = "arrow-back", iconCustom, + onPress, }: { path?: Href; icon?: React.ReactNode | any; iconCustom?: React.ReactNode; + onPress?: () => void; }) => { return ( <> @@ -26,7 +28,7 @@ const LeftButtonCustom = ({ name={icon} size={20} color={MainColor.yellow} - onPress={() => (path ? router.replace(path) : router.back())} + onPress={() => (onPress ? onPress() : path ? router.replace(path) : router.back())} /> )} diff --git a/screens/Admin/Job/funUpdateStatus.ts b/screens/Admin/Job/funUpdateStatus.ts index c875a2c..5e82cc3 100644 --- a/screens/Admin/Job/funUpdateStatus.ts +++ b/screens/Admin/Job/funUpdateStatus.ts @@ -7,7 +7,7 @@ const funUpdateStatusJob = async ({ }: { id: string; changeStatus: "publish" | "review" | "reject"; - data?: string; + data?: any; }) => { try { const response = await apiAdminJobUpdate({