complated project
This commit is contained in:
203
screens/profile/ui/RefferallsTab.tsx
Normal file
203
screens/profile/ui/RefferallsTab.tsx
Normal file
@@ -0,0 +1,203 @@
|
||||
import { useTheme } from '@/components/ThemeContext';
|
||||
import { useInfiniteQuery } from '@tanstack/react-query';
|
||||
import * as Clipboard from 'expo-clipboard';
|
||||
import { useRouter } from 'expo-router';
|
||||
import { ArrowLeft, CopyIcon, HandCoins, Plus, Users } from 'lucide-react-native';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
FlatList,
|
||||
Pressable,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
Text,
|
||||
ToastAndroid,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { user_api } from '../lib/api';
|
||||
|
||||
const PAGE_SIZE = 10;
|
||||
|
||||
export function ReferralsTab() {
|
||||
const router = useRouter();
|
||||
const { isDark } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
|
||||
const theme = {
|
||||
background: isDark ? '#0f172a' : '#f8fafc',
|
||||
cardBg: isDark ? '#1e293b' : '#ffffff',
|
||||
text: isDark ? '#ffffff' : '#0f172a',
|
||||
subText: isDark ? '#94a3b8' : '#64748b',
|
||||
primary: '#3b82f6',
|
||||
success: '#10b981',
|
||||
};
|
||||
|
||||
const { data, isLoading, isError, fetchNextPage, hasNextPage, refetch } = useInfiniteQuery({
|
||||
queryKey: ['my_referrals'],
|
||||
queryFn: async ({ pageParam = 1 }) => {
|
||||
const res = await user_api.my_referrals({
|
||||
page: pageParam,
|
||||
page_size: PAGE_SIZE,
|
||||
});
|
||||
|
||||
const d = res.data.data;
|
||||
return {
|
||||
results: d.results ?? [],
|
||||
current_page: d.current_page,
|
||||
total_pages: d.total_pages,
|
||||
};
|
||||
},
|
||||
getNextPageParam: (lastPage) =>
|
||||
lastPage.current_page < lastPage.total_pages ? lastPage.current_page + 1 : undefined,
|
||||
initialPageParam: 1,
|
||||
});
|
||||
|
||||
const referrals = data?.pages.flatMap((p) => p.results) ?? [];
|
||||
|
||||
const onRefresh = async () => {
|
||||
setRefreshing(true);
|
||||
await refetch();
|
||||
setRefreshing(false);
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1 }}>
|
||||
<ActivityIndicator size="large" />
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<View style={[styles.center, { backgroundColor: theme.background }]}>
|
||||
<Text style={{ color: 'red' }}>{t('Xatolik yuz berdi')}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: theme.background }]}>
|
||||
{/* Header */}
|
||||
<View style={styles.topHeader}>
|
||||
<Pressable onPress={() => router.push('/profile')}>
|
||||
<ArrowLeft color={theme.text} />
|
||||
</Pressable>
|
||||
<Text style={[styles.headerTitle, { color: theme.text }]}>{t('Refferallarim')}</Text>
|
||||
<Pressable onPress={() => router.push('/profile/added-referalls')}>
|
||||
<Plus color={theme.primary} />
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
<FlatList
|
||||
data={referrals}
|
||||
keyExtractor={(item) => item.id.toString()}
|
||||
contentContainerStyle={styles.list}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} tintColor={theme.primary} />
|
||||
}
|
||||
onEndReached={() => hasNextPage && fetchNextPage()}
|
||||
renderItem={({ item }) => (
|
||||
<View style={[styles.card, { backgroundColor: theme.cardBg }]}>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<View style={styles.cardHeader}>
|
||||
<HandCoins size={20} color={theme.primary} />
|
||||
<Text style={[styles.code, { color: theme.text }]}>{item.code}</Text>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
onPress={async () => {
|
||||
await Clipboard.setStringAsync(
|
||||
`https://t.me/infotargetbot/join?startapp=${item.code}`
|
||||
);
|
||||
ToastAndroid.show('Refferal kopiya qilindi', ToastAndroid.SHORT);
|
||||
}}
|
||||
>
|
||||
<CopyIcon size={20} color={theme.primary} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<Text style={{ color: theme.subText }}>{item.description}</Text>
|
||||
|
||||
<View style={styles.footer}>
|
||||
<View style={styles.row}>
|
||||
<Users size={16} color={theme.subText} />
|
||||
<Text style={[styles.meta, { color: theme.subText }]}>
|
||||
{item.referral_registered_count} {t('foydalanuvchi')}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<Text style={[styles.amount, { color: theme.success }]}>
|
||||
{item.referral_income_amount} {t("so'm")}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
ListEmptyComponent={
|
||||
<Text style={{ textAlign: 'center', color: theme.subText }}>
|
||||
{t('Refferallar topilmadi')}
|
||||
</Text>
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1 },
|
||||
center: { flex: 1, justifyContent: 'center', alignItems: 'center' },
|
||||
|
||||
topHeader: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
padding: 16,
|
||||
alignItems: 'center',
|
||||
},
|
||||
headerTitle: { fontSize: 18, fontWeight: '700' },
|
||||
|
||||
list: { padding: 16, gap: 12 },
|
||||
|
||||
card: {
|
||||
borderRadius: 16,
|
||||
padding: 16,
|
||||
gap: 10,
|
||||
},
|
||||
|
||||
cardHeader: {
|
||||
flexDirection: 'row',
|
||||
gap: 8,
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
code: {
|
||||
fontSize: 16,
|
||||
fontWeight: '700',
|
||||
},
|
||||
|
||||
footer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginTop: 6,
|
||||
},
|
||||
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
gap: 6,
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
meta: {},
|
||||
amount: {
|
||||
fontWeight: '700',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user