upd: caching data
Deskripsi: - update caching pada fitur utama -yg fitur divisi belom
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import styles from "@/components/AppHeader"
|
||||
import AppHeader from "@/components/AppHeader"
|
||||
import HeaderRightBannerList from "@/components/banner/headerBannerList"
|
||||
import BorderBottomItem from "@/components/borderBottomItem"
|
||||
@@ -5,6 +6,7 @@ import DrawerBottom from "@/components/drawerBottom"
|
||||
import MenuItemRow from "@/components/menuItemRow"
|
||||
import ModalConfirmation from "@/components/ModalConfirmation"
|
||||
import ModalLoading from "@/components/modalLoading"
|
||||
import Skeleton from "@/components/skeleton"
|
||||
import Text from "@/components/Text"
|
||||
import { ConstEnv } from "@/constants/ConstEnv"
|
||||
import Styles from "@/constants/Styles"
|
||||
@@ -13,11 +15,12 @@ import { setEntities } from "@/lib/bannerSlice"
|
||||
import { useAuthSession } from "@/providers/AuthProvider"
|
||||
import { useTheme } from "@/providers/ThemeProvider"
|
||||
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons"
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
||||
import * as FileSystem from 'expo-file-system'
|
||||
import { startActivityAsync } from 'expo-intent-launcher'
|
||||
import { router, Stack } from "expo-router"
|
||||
import * as Sharing from 'expo-sharing'
|
||||
import { useState } from "react"
|
||||
import { useEffect, useState } from "react"
|
||||
import { Alert, Image, Platform, RefreshControl, SafeAreaView, ScrollView, View } from "react-native"
|
||||
import ImageViewing from 'react-native-image-viewing'
|
||||
import * as mime from 'react-native-mime-types'
|
||||
@@ -43,36 +46,51 @@ export default function BannerList() {
|
||||
const [loadingOpen, setLoadingOpen] = useState(false)
|
||||
const [viewImg, setViewImg] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const handleDeleteEntity = async () => {
|
||||
try {
|
||||
const hasil = await decryptToken(String(token?.current));
|
||||
const deletedEntity = await apiDeleteBanner({ user: hasil }, dataId);
|
||||
if (deletedEntity.success) {
|
||||
Toast.show({ type: 'small', text1: 'Berhasil menghapus data', })
|
||||
apiGetBanner({ user: hasil }).then((data) =>
|
||||
dispatch(setEntities(data.data))
|
||||
);
|
||||
} else {
|
||||
Toast.show({ type: 'small', text1: 'Gagal menghapus data', })
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
const message = error?.response?.data?.message || "Gagal menghapus data"
|
||||
// 1. Fetching logic with useQuery
|
||||
const { data: bannersRes, isLoading } = useQuery({
|
||||
queryKey: ['banners'],
|
||||
queryFn: async () => {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
const response = await apiGetBanner({ user: hasil })
|
||||
return response.data || []
|
||||
},
|
||||
enabled: !!token?.current,
|
||||
staleTime: 0,
|
||||
})
|
||||
|
||||
Toast.show({ type: 'small', text1: message })
|
||||
} finally {
|
||||
setModal(false)
|
||||
// Sync results with Redux
|
||||
useEffect(() => {
|
||||
if (bannersRes) {
|
||||
dispatch(setEntities(bannersRes))
|
||||
}
|
||||
}, [bannersRes, dispatch])
|
||||
|
||||
// 2. Deletion logic with useMutation
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const hasil = await decryptToken(String(token?.current))
|
||||
return await apiDeleteBanner({ user: hasil }, id)
|
||||
},
|
||||
onSuccess: () => {
|
||||
Toast.show({ type: 'small', text1: 'Berhasil menghapus data' })
|
||||
queryClient.invalidateQueries({ queryKey: ['banners'] })
|
||||
},
|
||||
onError: (error: any) => {
|
||||
const message = error?.response?.data?.message || "Gagal menghapus data"
|
||||
Toast.show({ type: 'small', text1: message })
|
||||
}
|
||||
})
|
||||
|
||||
const handleDeleteEntity = () => {
|
||||
deleteMutation.mutate(dataId)
|
||||
setModal(false)
|
||||
};
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setRefreshing(true)
|
||||
const hasil = await decryptToken(String(token?.current));
|
||||
apiGetBanner({ user: hasil }).then((data) =>
|
||||
dispatch(setEntities(data.data))
|
||||
);
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
await queryClient.invalidateQueries({ queryKey: ['banners'] })
|
||||
setRefreshing(false)
|
||||
};
|
||||
|
||||
@@ -140,36 +158,40 @@ export default function BannerList() {
|
||||
}
|
||||
style={[Styles.h100, { backgroundColor: colors.background }]}
|
||||
>
|
||||
{
|
||||
entities.length > 0
|
||||
?
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
{entities.map((index: any, key: number) => (
|
||||
<BorderBottomItem
|
||||
key={key}
|
||||
onPress={() => {
|
||||
setDataId(index.id)
|
||||
setSelectFile(index)
|
||||
setModal(true)
|
||||
}}
|
||||
borderType="all"
|
||||
icon={
|
||||
<Image
|
||||
source={{ uri: `${ConstEnv.url_storage}/files/${index.image}` }}
|
||||
style={[Styles.imgListBanner]}
|
||||
/>
|
||||
}
|
||||
title={index.title}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
:
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<Text style={[Styles.textDefault, Styles.textCenter]}>Tidak ada data</Text>
|
||||
</View>
|
||||
}
|
||||
|
||||
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
{
|
||||
isLoading ? (
|
||||
<>
|
||||
<Skeleton width={100} height={150} borderRadius={10} widthType="percent" />
|
||||
<Skeleton width={100} height={150} borderRadius={10} widthType="percent" />
|
||||
<Skeleton width={100} height={150} borderRadius={10} widthType="percent" />
|
||||
</>
|
||||
) :
|
||||
entities.length > 0 ?
|
||||
entities.map((index: any, key: number) => (
|
||||
<BorderBottomItem
|
||||
key={key}
|
||||
onPress={() => {
|
||||
setDataId(index.id)
|
||||
setSelectFile(index)
|
||||
setModal(true)
|
||||
}}
|
||||
borderType="all"
|
||||
icon={
|
||||
<Image
|
||||
source={{ uri: `${ConstEnv.url_storage}/files/${index.image}` }}
|
||||
style={[Styles.imgListBanner]}
|
||||
/>
|
||||
}
|
||||
title={index.title}
|
||||
/>
|
||||
))
|
||||
:
|
||||
<View style={[Styles.p15, Styles.mb100]}>
|
||||
<Text style={[Styles.textDefault, Styles.textCenter]}>Tidak ada data</Text>
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
<DrawerBottom animation="slide" isVisible={isModal} setVisible={() => setModal(false)} title="Menu">
|
||||
|
||||
Reference in New Issue
Block a user