feat: tambah fitur tandai semua notifikasi dibaca dengan modal konfirmasi

This commit is contained in:
2026-05-08 14:56:44 +08:00
parent 4eebf2f893
commit 4af54980a0
2 changed files with 55 additions and 3 deletions

View File

@@ -1,8 +1,9 @@
import AppHeader from "@/components/AppHeader";
import ModalConfirmation from "@/components/ModalConfirmation";
import SkeletonTwoItem from "@/components/skeletonTwoItem";
import Text from "@/components/Text";
import Styles from "@/constants/Styles";
import { apiGetNotification, apiReadOneNotification } from "@/lib/api";
import { apiGetNotification, apiReadAllNotification, apiReadOneNotification } from "@/lib/api";
import { setUpdateNotification } from "@/lib/notificationSlice";
import { pushToPage } from "@/lib/pushToPage";
import { useAuthSession } from "@/providers/AuthProvider";
@@ -32,7 +33,7 @@ type ListRow = HeaderRow | ItemRow
function getNotifStyle(category: string): { icon: keyof typeof Feather.glyphMap; color: string } {
if (category === 'announcement') return { icon: 'volume-2', color: '#3B82F6' }
if (category === 'project') return { icon: 'activity', color: '#10B981' }
if (category.includes('/task')) return { icon: 'check-circle', color: '#8B5CF6' }
if (category.includes('/task')) return { icon: 'clipboard', color: '#8B5CF6' }
if (category === 'division') return { icon: 'users', color: '#3B82F6' }
if (category.includes('/discussion') || category === 'discussion-general') return { icon: 'message-square', color: '#06B6D4' }
if (category.includes('/calendar')) return { icon: 'calendar', color: '#F59E0B' }
@@ -48,6 +49,8 @@ export default function Notification() {
const dispatch = useDispatch()
const updateNotification = useSelector((state: any) => state.notificationUpdate)
const [refreshing, setRefreshing] = useState(false)
const [markingAll, setMarkingAll] = useState(false)
const [showConfirm, setShowConfirm] = useState(false)
const {
data,
@@ -106,6 +109,22 @@ export default function Notification() {
setRefreshing(false)
};
const hasUnread = flatData.some((item) => !item.isRead)
async function handleReadAll() {
try {
setMarkingAll(true)
const hasil = await decryptToken(String(token?.current))
await apiReadAllNotification({ user: hasil })
await queryClient.invalidateQueries({ queryKey: ['notifications'] })
dispatch(setUpdateNotification(!updateNotification))
} catch (error) {
console.error(error)
} finally {
setMarkingAll(false)
}
}
async function handleReadNotification(id: string, category: string, idContent: string) {
try {
const hasil = await decryptToken(String(token?.current))
@@ -123,11 +142,39 @@ export default function Notification() {
<Stack.Screen
options={{
header: () => (
<AppHeader title="Notifikasi" showBack={true} onPressLeft={() => router.back()} />
<AppHeader
title="Notifikasi"
showBack={true}
onPressLeft={() => router.back()}
right={
hasUnread ? (
<Pressable
onPress={() => setShowConfirm(true)}
disabled={markingAll}
style={{ opacity: markingAll ? 0.5 : 1, padding: 4 }}
>
<Feather name="check-square" size={22} color="white" />
</Pressable>
) : undefined
}
/>
)
}}
/>
<ModalConfirmation
visible={showConfirm}
title="Tandai Semua Dibaca"
message="Semua notifikasi akan ditandai sebagai telah dibaca."
confirmText="Tandai"
cancelText="Batal"
onConfirm={() => {
setShowConfirm(false)
handleReadAll()
}}
onCancel={() => setShowConfirm(false)}
/>
<View style={[Styles.flex1, Styles.ph15, { paddingTop: 10 }]}>
{isLoading ? (
[0, 1, 2, 3, 4].map((_, i) => <SkeletonTwoItem key={i} />)