fitst commit
This commit is contained in:
115
screens/announcements/ui/AnnouncementsList.tsx
Normal file
115
screens/announcements/ui/AnnouncementsList.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import { useTheme } from '@/components/ThemeContext';
|
||||
import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ActivityIndicator, Animated, RefreshControl, StyleSheet, Text, View } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { announcement_api } from '../lib/api';
|
||||
import { AnnouncementListBodyRes } from '../lib/type';
|
||||
import AnnouncementCard from './AnnouncementCard';
|
||||
import EmptyState from './EmptyState';
|
||||
|
||||
export default function DashboardScreen() {
|
||||
const [announcements, setAnnouncements] = useState<AnnouncementListBodyRes[]>([]);
|
||||
const queryClient = useQueryClient();
|
||||
const fadeAnim = useRef(new Animated.Value(0)).current;
|
||||
const { isDark } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const theme = {
|
||||
background: isDark ? '#0f172a' : '#f8fafc',
|
||||
primary: '#2563eb',
|
||||
loaderBg: isDark ? '#0f172a' : '#ffffff',
|
||||
};
|
||||
|
||||
const { data, isLoading, isRefetching, fetchNextPage, hasNextPage } = useInfiniteQuery({
|
||||
queryKey: ['announcements_list'],
|
||||
queryFn: async ({ pageParam = 1 }) => {
|
||||
const res = await announcement_api.list({ page: pageParam, page_size: 10 });
|
||||
return res.data.data;
|
||||
},
|
||||
getNextPageParam: (lastPage) =>
|
||||
lastPage.current_page < lastPage.total_pages ? lastPage.current_page + 1 : undefined,
|
||||
initialPageParam: 1,
|
||||
});
|
||||
|
||||
const allAnnouncements = data?.pages.flatMap((p) => p.results) ?? [];
|
||||
|
||||
useEffect(() => {
|
||||
setAnnouncements(allAnnouncements);
|
||||
|
||||
fadeAnim.setValue(0);
|
||||
Animated.timing(fadeAnim, {
|
||||
toValue: 1,
|
||||
duration: 300,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
}, [allAnnouncements]);
|
||||
|
||||
const onRefresh = () => {
|
||||
queryClient.refetchQueries({ queryKey: ['announcements_list'] });
|
||||
};
|
||||
|
||||
const loadMore = () => {
|
||||
if (hasNextPage) fetchNextPage();
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
|
||||
<View style={[styles.loaderBox, { backgroundColor: theme.loaderBg }]}>
|
||||
<ActivityIndicator size="large" color={theme.primary} />
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: theme.background }]}>
|
||||
<Text style={{ color: 'white', fontSize: 20, marginBottom: 10 }}>
|
||||
{t("E'lonlar ro'yxati")}
|
||||
</Text>
|
||||
{announcements.length > 0 ? (
|
||||
<Animated.FlatList
|
||||
style={{ flex: 1 }}
|
||||
data={announcements}
|
||||
keyExtractor={(item) => item.id.toString()}
|
||||
numColumns={2}
|
||||
columnWrapperStyle={styles.columnWrapper}
|
||||
renderItem={({ item }) => <AnnouncementCard announcement={item} />}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={isRefetching}
|
||||
onRefresh={onRefresh}
|
||||
colors={[theme.primary]}
|
||||
tintColor={theme.primary}
|
||||
progressBackgroundColor={theme.background}
|
||||
/>
|
||||
}
|
||||
onEndReached={loadMore}
|
||||
onEndReachedThreshold={0.3}
|
||||
showsVerticalScrollIndicator={false}
|
||||
/>
|
||||
) : (
|
||||
<EmptyState onRefresh={onRefresh} isRefreshing={isRefetching} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 16,
|
||||
marginTop: 20,
|
||||
},
|
||||
loaderBox: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
columnWrapper: {
|
||||
justifyContent: 'space-between',
|
||||
gap: 12,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user