fix: list data

Deskripsi:
- perbaikan list data pada jabatan dan group menggunakan virtualized

No Issues
This commit is contained in:
2025-08-11 10:43:50 +08:00
parent fce5465d4b
commit f929791075
2 changed files with 113 additions and 93 deletions

View File

@@ -15,7 +15,7 @@ import { setUpdateGroup } from "@/lib/groupSlice";
import { useAuthSession } from "@/providers/AuthProvider"; import { useAuthSession } from "@/providers/AuthProvider";
import { AntDesign, Feather, MaterialCommunityIcons } from "@expo/vector-icons"; import { AntDesign, Feather, MaterialCommunityIcons } from "@expo/vector-icons";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { RefreshControl, SafeAreaView, ScrollView, View } from "react-native"; import { RefreshControl, View, VirtualizedList } from "react-native";
import Toast from "react-native-toast-message"; import Toast from "react-native-toast-message";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
@@ -116,9 +116,17 @@ export default function Index() {
} }
const getItem = (_data: unknown, index: number): Props => ({
id: data[index].id,
name: data[index].name,
isActive: data[index].isActive,
});
return ( return (
<SafeAreaView> <View style={[Styles.p15, { flex: 1 }]}>
<View style={[Styles.p15]}> <View>
<View style={[Styles.wrapBtnTab]}> <View style={[Styles.wrapBtnTab]}>
<ButtonTab <ButtonTab
active={status == "false" ? "false" : "true"} active={status == "false" ? "false" : "true"}
@@ -136,51 +144,53 @@ export default function Index() {
n={2} /> n={2} />
</View> </View>
<InputSearch onChange={setSearch} /> <InputSearch onChange={setSearch} />
<ScrollView </View>
refreshControl={ <View style={{ flex: 2 }}>
<RefreshControl {
refreshing={refreshing} loading ?
onRefresh={handleRefresh} arrSkeleton.map((item, index) => {
/> return (
} <SkeletonTwoItem key={index} />
style={[Styles.h100]} )
> })
<View> :
{ data.length > 0 ?
<VirtualizedList
loading ? data={data}
arrSkeleton.map((item, index) => { getItemCount={() => data.length}
getItem={getItem}
renderItem={({ item, index }: { item: Props, index: number }) => {
return ( return (
<SkeletonTwoItem key={index} /> <BorderBottomItem
key={index}
onPress={() => {
setIdChoose(item.id)
setActiveChoose(item.isActive)
setTitleChoose(item.name)
setModal(true)
}}
borderType="all"
icon={
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
<MaterialCommunityIcons name="office-building-outline" size={25} color={'#384288'} />
</View>
}
title={item.name}
/>
) )
}) }}
: keyExtractor={(item, index) => String(index)}
data.length > 0 ? showsVerticalScrollIndicator={false}
data.map((item, index) => { refreshControl={
return ( <RefreshControl
<BorderBottomItem refreshing={refreshing}
key={index} onRefresh={handleRefresh}
onPress={() => { />
setIdChoose(item.id) }
setActiveChoose(item.isActive) />
setTitleChoose(item.name) :
setModal(true) <Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada data</Text>
}} }
borderType="all"
icon={
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
<MaterialCommunityIcons name="office-building-outline" size={25} color={'#384288'} />
</View>
}
title={item.name}
/>
)
})
:
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada data</Text>
}
</View>
</ScrollView>
</View> </View>
<DrawerBottom animation="slide" isVisible={isModal} setVisible={() => setModal(false)} title={titleChoose}> <DrawerBottom animation="slide" isVisible={isModal} setVisible={() => setModal(false)} title={titleChoose}>
@@ -228,8 +238,7 @@ export default function Index() {
</View> </View>
</View> </View>
</DrawerBottom> </DrawerBottom>
</View >
</SafeAreaView>
) )
} }

View File

@@ -16,7 +16,7 @@ import { useAuthSession } from "@/providers/AuthProvider";
import { AntDesign, Feather, MaterialCommunityIcons } from "@expo/vector-icons"; import { AntDesign, Feather, MaterialCommunityIcons } from "@expo/vector-icons";
import { useLocalSearchParams } from "expo-router"; import { useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { RefreshControl, SafeAreaView, ScrollView, View } from "react-native"; import { RefreshControl, View, VirtualizedList } from "react-native";
import Toast from "react-native-toast-message"; import Toast from "react-native-toast-message";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
@@ -129,9 +129,18 @@ export default function Index() {
setRefreshing(false) setRefreshing(false)
}; };
const getItem = (_data: unknown, index: number): Props => ({
id: data[index].id,
name: data[index].name,
idGroup: data[index].idGroup,
group: data[index].group,
isActive: data[index].isActive,
});
return ( return (
<SafeAreaView> <View style={[Styles.p15, { flex: 1 }]}>
<View style={[Styles.p15]}> <View>
<View style={[Styles.wrapBtnTab]}> <View style={[Styles.wrapBtnTab]}>
<ButtonTab <ButtonTab
active={status == "false" ? "false" : "true"} active={status == "false" ? "false" : "true"}
@@ -155,47 +164,50 @@ export default function Index() {
<Text>Filter : {nameGroup}</Text> <Text>Filter : {nameGroup}</Text>
</View> </View>
} }
<ScrollView
style={[Styles.h100]}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={handleRefresh}
/>
}>
<View>
{
loading ?
arrSkeleton.map((item, index) => {
return (
<SkeletonTwoItem key={index} />
)
})
:
data.length > 0 ?
data.map((item, index) => {
return (
<BorderBottomItem
key={index}
onPress={() => { handleChooseData(item.id, item.name, item.isActive, item.idGroup) }}
borderType="all"
icon={
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
<MaterialCommunityIcons name="account-tie" size={25} color={'#384288'} />
</View>
}
title={item.name}
subtitle={item.group}
/>
)
})
:
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada data</Text>
}
</View>
</ScrollView>
</View> </View>
<View style={[{ flex: 2 }]}>
{
loading ?
arrSkeleton.map((item, index) => {
return (
<SkeletonTwoItem key={index} />
)
})
:
data.length > 0 ?
<VirtualizedList
data={data}
getItemCount={() => data.length}
getItem={getItem}
renderItem={({ item, index }: { item: Props, index: number }) => {
return (
<BorderBottomItem
key={index}
onPress={() => { handleChooseData(item.id, item.name, item.isActive, item.idGroup) }}
borderType="all"
icon={
<View style={[Styles.iconContent, ColorsStatus.lightGreen]}>
<MaterialCommunityIcons name="account-tie" size={25} color={'#384288'} />
</View>
}
title={item.name}
subtitle={item.group}
/>
)
}}
keyExtractor={(item, index) => String(index)}
showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={handleRefresh}
/>
}
/>
:
<Text style={[Styles.textDefault, Styles.cGray, { textAlign: 'center' }]}>Tidak ada data</Text>
}
</View>
<DrawerBottom animation="slide" isVisible={isModal} setVisible={() => setModal(false)} title={chooseData.name}> <DrawerBottom animation="slide" isVisible={isModal} setVisible={() => setModal(false)} title={chooseData.name}>
<View style={Styles.rowItemsCenter}> <View style={Styles.rowItemsCenter}>
<MenuItemRow <MenuItemRow
@@ -243,7 +255,6 @@ export default function Index() {
</View> </View>
</View> </View>
</DrawerBottom> </DrawerBottom>
</View>
</SafeAreaView>
) )
} }