import { useTheme } from '@/components/ThemeContext'; import { useInfiniteQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { router } from 'expo-router'; import { ArrowLeft } from 'lucide-react-native'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ActivityIndicator, Animated, FlatList, Pressable, StyleSheet, Text, TouchableOpacity, View, } from 'react-native'; import { user_api } from '../lib/api'; import { NotificationListDataRes } from '../lib/type'; const PAGE_SIZE = 10; export function NotificationTab() { const { isDark } = useTheme(); const { t } = useTranslation(); const { data, isLoading, isError, fetchNextPage, hasNextPage, isFetchingNextPage, refetch } = useInfiniteQuery({ queryKey: ['notifications-list'], queryFn: async ({ pageParam = 1 }) => { const response = await user_api.notification_list({ page: pageParam, page_size: PAGE_SIZE, }); return response.data.data; }, getNextPageParam: (lastPage) => lastPage.current_page < lastPage.total_pages ? lastPage.current_page + 1 : undefined, initialPageParam: 1, }); const notifications = data?.pages.flatMap((p) => p.results) ?? []; if (isLoading) { return ( ); } if (isError) { return ( {t('Xatolik yuz berdi')} {t("Bildirishnomalarni yuklashda muammo bo'ldi")} refetch()}> {t('Qayta urinish')} ); } return ( router.push('/profile')}> {t('Bildirishnomalar')} item.id.toString()} contentContainerStyle={styles.listContent} showsVerticalScrollIndicator={false} renderItem={({ item, index }) => } onEndReached={() => { if (hasNextPage && !isFetchingNextPage) { fetchNextPage(); } }} onEndReachedThreshold={0.5} ListFooterComponent={ isFetchingNextPage ? ( ) : null } refreshing={isLoading} onRefresh={refetch} /> ); } /* ---------------- CARD ---------------- */ function NotificationCard({ item }: { item: NotificationListDataRes }) { const queryClient = useQueryClient(); const { t } = useTranslation(); const [scaleAnim] = useState(new Animated.Value(1)); const { mutate } = useMutation({ mutationFn: (id: number) => user_api.is_ready_id(id), onSuccess: () => { queryClient.refetchQueries({ queryKey: ['notification-list'] }); }, }); const handlePressIn = () => { Animated.spring(scaleAnim, { toValue: 0.96, useNativeDriver: true, }).start(); }; const handlePressOut = () => { Animated.spring(scaleAnim, { toValue: 1, friction: 4, tension: 50, useNativeDriver: true, }).start(); }; const handlePress = (id: number) => { if (!item.is_read) { mutate(id); } }; return ( handlePress(item.id)} style={[styles.card, !item.is_read && styles.unreadCard]} > {item.title} {!item.is_read && } {item.description} {formatDate(item.created_at, t)} ); } /* ---------------- HELPERS ---------------- */ function formatDate(date: string, t: any) { const now = new Date(); const notifDate = new Date(date); const diffMs = now.getTime() - notifDate.getTime(); const diffMins = Math.floor(diffMs / 60000); const diffHours = Math.floor(diffMs / 3600000); const diffDays = Math.floor(diffMs / 86400000); if (diffMins < 1) return 'Hozir'; if (diffMins < 60) return `${diffMins} ${t('daqiqa oldin')}`; if (diffHours < 24) return `${diffHours} ${t('soat oldin')}`; if (diffDays < 7) return `${diffDays} ${t('kun oldin')}`; return notifDate.toLocaleDateString('uz-UZ', { day: 'numeric', month: 'short', }); } /* ---------------- STYLES ---------------- */ const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#0a0c17', }, listContent: { padding: 16, paddingBottom: 32, }, /* Card Styles */ card: { flexDirection: 'row', backgroundColor: '#121826', padding: 16, borderRadius: 24, borderWidth: 1, borderColor: 'rgba(60, 70, 90, 0.18)', shadowColor: '#000', shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.35, shadowRadius: 16, elevation: 10, overflow: 'hidden', }, unreadCard: { backgroundColor: '#1a2236', borderColor: 'rgba(59, 130, 246, 0.4)', shadowColor: '#3b82f6', shadowOpacity: 0.28, shadowRadius: 20, elevation: 12, }, iconContainer: { width: 56, height: 56, borderRadius: 20, backgroundColor: 'rgba(30, 38, 56, 0.7)', alignItems: 'center', justifyContent: 'center', marginRight: 16, }, unreadIconContainer: { backgroundColor: 'rgba(59, 130, 246, 0.22)', }, iconText: { fontSize: 32, }, cardContent: { flex: 1, justifyContent: 'center', }, cardHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 6, }, cardTitle: { flex: 1, color: '#d1d5db', fontSize: 16.5, fontWeight: '600', letterSpacing: -0.1, }, unreadTitle: { color: '#f1f5f9', fontWeight: '700', }, unreadIndicator: { width: 10, height: 10, borderRadius: 5, backgroundColor: '#3b82f6', marginLeft: 8, shadowColor: '#3b82f6', shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0.7, shadowRadius: 6, }, cardMessage: { color: '#9ca3af', fontSize: 14.5, lineHeight: 21, marginBottom: 8, }, cardTime: { color: '#64748b', fontSize: 12.5, fontWeight: '500', opacity: 0.9, }, /* Loading State */ loadingContainer: { flex: 1, backgroundColor: '#0a0c17', alignItems: 'center', justifyContent: 'center', }, loadingContent: { alignItems: 'center', padding: 32, }, loadingText: { marginTop: 16, color: '#94a3b8', fontSize: 15, fontWeight: '500', }, /* Error State */ errorContainer: { flex: 1, backgroundColor: '#0a0c17', alignItems: 'center', justifyContent: 'center', padding: 24, }, errorContent: { alignItems: 'center', backgroundColor: '#151b2e', padding: 32, borderRadius: 24, maxWidth: 320, }, errorIconContainer: { width: 80, height: 80, borderRadius: 40, backgroundColor: '#1e2638', alignItems: 'center', justifyContent: 'center', marginBottom: 20, }, errorIcon: { fontSize: 40, }, errorTitle: { color: '#ef4444', fontSize: 20, fontWeight: '700', marginBottom: 8, }, errorMessage: { color: '#94a3b8', fontSize: 14, textAlign: 'center', marginBottom: 24, lineHeight: 20, }, retryButton: { backgroundColor: '#3b82f6', paddingHorizontal: 32, paddingVertical: 14, borderRadius: 12, shadowColor: '#3b82f6', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 8, elevation: 5, }, retryButtonText: { color: '#ffffff', fontSize: 15, fontWeight: '700', }, /* Empty State */ emptyContainer: { flex: 1, backgroundColor: '#0a0c17', alignItems: 'center', justifyContent: 'center', padding: 24, }, emptyContent: { alignItems: 'center', maxWidth: 300, }, emptyIconContainer: { width: 100, height: 100, borderRadius: 50, backgroundColor: '#151b2e', alignItems: 'center', justifyContent: 'center', marginBottom: 24, borderWidth: 2, borderColor: '#1e2638', }, emptyIcon: { fontSize: 50, }, emptyTitle: { color: '#ffffff', fontSize: 22, fontWeight: '700', marginBottom: 12, textAlign: 'center', }, emptyMessage: { color: '#94a3b8', fontSize: 15, textAlign: 'center', lineHeight: 22, }, header: { padding: 16, flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start', gap: 10, elevation: 3, }, headerTitle: { fontSize: 18, fontWeight: '700', lineHeight: 24 }, });