import {
View, Text, FlatList, TouchableOpacity, RefreshControl, ScrollView, StyleSheet, Animated,
} from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import { useState, useEffect, useRef, useCallback } from 'react'
import { useRouter } from 'expo-router'
import { useFocusEffect } from 'expo-router'
import { useNewsList } from '@/hooks/useNews'
import { NewsCard } from '@/components/news/NewsCard'
import { EmptyState } from '@/components/ui/EmptyState'
import { LoadingSpinner } from '@/components/ui/LoadingSpinner'
import { useNewsReadStore } from '@/store/news.store'
function SkeletonCard() {
const anim = useRef(new Animated.Value(0.4)).current
useEffect(() => {
Animated.loop(
Animated.sequence([
Animated.timing(anim, { toValue: 1, duration: 800, useNativeDriver: true }),
Animated.timing(anim, { toValue: 0.4, duration: 800, useNativeDriver: true }),
])
).start()
}, [])
return (
)
}
const skeletonStyles = StyleSheet.create({
card: { backgroundColor: '#FFFFFF', borderRadius: 12, padding: 16, marginBottom: 10, marginHorizontal: 16 },
badge: { height: 20, width: 80, borderRadius: 10, backgroundColor: '#E2E8F0', marginBottom: 12 },
titleLine: { height: 16, borderRadius: 8, backgroundColor: '#E2E8F0', width: '85%', marginBottom: 8 },
titleLineShort: { height: 16, borderRadius: 8, backgroundColor: '#E2E8F0', width: '55%', marginBottom: 12 },
metaLine: { height: 12, borderRadius: 6, backgroundColor: '#F1F5F9', width: '40%' },
})
const FILTERS = [
{ value: undefined, label: 'Alle' },
{ value: 'Wichtig', label: 'Wichtig' },
{ value: 'Pruefung', label: 'Pruefung' },
{ value: 'Foerderung', label: 'Foerderung' },
{ value: 'Veranstaltung', label: 'Veranstaltung' },
]
export default function NewsScreen() {
const router = useRouter()
const [kategorie, setKategorie] = useState(undefined)
const [showSkeleton, setShowSkeleton] = useState(true)
// Fetch all news (without category filter) to compute per-category unread counts
const { data: allData, refetch: refetchAll, isRefetching: isRefetchingAll } = useNewsList(undefined)
const { data, isLoading, refetch, isRefetching } = useNewsList(kategorie)
const localReadIds = useNewsReadStore((s) => s.readIds)
useFocusEffect(
useCallback(() => {
setShowSkeleton(true)
const t = setTimeout(() => setShowSkeleton(false), 800)
return () => clearTimeout(t)
}, [])
)
// Compute unread count per category (combining server isRead + local store)
function getUnreadCount(filterValue: string | undefined) {
const source = allData ?? []
const filtered = filterValue === undefined
? source
: source.filter((n) => n.kategorie === filterValue)
return filtered.filter((n) => !n.isRead && !localReadIds.has(n.id)).length
}
return (
Aktuelles
{FILTERS.map((opt) => {
const active = kategorie === opt.value
const count = getUnreadCount(opt.value)
return (
setKategorie(opt.value)}
style={[styles.chip, active && styles.chipActive]}
activeOpacity={0.85}
>
{opt.label}
{count > 0 && (
{count}
)}
)
})}
{showSkeleton ? (
{[1,2,3,4].map((i) => )}
) : (
item.id}
contentContainerStyle={styles.list}
initialNumToRender={10}
maxToRenderPerBatch={10}
windowSize={5}
refreshControl={
}
renderItem={({ item }) => (
router.push(`/(app)/news/${item.id}` as never)}
/>
)}
ListEmptyComponent={
}
/>
)}
)
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: '#F8FAFC',
},
header: {
backgroundColor: '#FFFFFF',
paddingHorizontal: 20,
paddingTop: 14,
paddingBottom: 0,
},
titleRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 14,
},
screenTitle: {
fontSize: 28,
fontWeight: '800',
color: '#0F172A',
letterSpacing: -0.5,
},
filterScroll: {
paddingBottom: 14,
gap: 8,
paddingRight: 20,
},
chip: {
flexDirection: 'row',
alignItems: 'center',
gap: 5,
paddingHorizontal: 14,
paddingVertical: 7,
borderRadius: 99,
borderWidth: 1,
borderColor: '#E2E8F0',
backgroundColor: '#FFFFFF',
},
chipActive: {
backgroundColor: '#003B7E',
borderColor: '#003B7E',
},
chipLabel: {
fontSize: 13,
fontWeight: '600',
color: '#64748B',
},
chipLabelActive: {
color: '#FFFFFF',
},
chipBadge: {
backgroundColor: '#003B7E',
borderRadius: 99,
minWidth: 18,
height: 18,
paddingHorizontal: 5,
alignItems: 'center',
justifyContent: 'center',
},
chipBadgeActive: {
backgroundColor: '#FFFFFF',
},
chipBadgeText: {
fontSize: 10,
fontWeight: '700',
color: '#FFFFFF',
},
chipBadgeTextActive: {
color: '#003B7E',
},
divider: {
height: 1,
backgroundColor: '#E2E8F0',
},
list: {
padding: 16,
gap: 10,
paddingBottom: 30,
},
})