push
This commit is contained in:
@@ -1,14 +1,43 @@
|
||||
import {
|
||||
View, Text, FlatList, TouchableOpacity, RefreshControl, ScrollView, StyleSheet,
|
||||
View, Text, FlatList, TouchableOpacity, RefreshControl, ScrollView, StyleSheet, Animated,
|
||||
} from 'react-native'
|
||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||
import { useState } from 'react'
|
||||
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'
|
||||
|
||||
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 (
|
||||
<Animated.View style={[skeletonStyles.card, { opacity: anim }]}>
|
||||
<View style={skeletonStyles.badge} />
|
||||
<View style={skeletonStyles.titleLine} />
|
||||
<View style={skeletonStyles.titleLineShort} />
|
||||
<View style={skeletonStyles.metaLine} />
|
||||
</Animated.View>
|
||||
)
|
||||
}
|
||||
|
||||
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' },
|
||||
@@ -20,8 +49,17 @@ const FILTERS = [
|
||||
export default function NewsScreen() {
|
||||
const router = useRouter()
|
||||
const [kategorie, setKategorie] = useState<string | undefined>(undefined)
|
||||
const [showSkeleton, setShowSkeleton] = useState(true)
|
||||
const { data, isLoading, refetch, isRefetching } = useNewsList(kategorie)
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
setShowSkeleton(true)
|
||||
const t = setTimeout(() => setShowSkeleton(false), 800)
|
||||
return () => clearTimeout(t)
|
||||
}, [])
|
||||
)
|
||||
|
||||
const unreadCount = data?.filter((n) => !n.isRead).length ?? 0
|
||||
|
||||
return (
|
||||
@@ -61,15 +99,20 @@ export default function NewsScreen() {
|
||||
|
||||
<View style={styles.divider} />
|
||||
|
||||
{isLoading ? (
|
||||
<LoadingSpinner />
|
||||
{showSkeleton ? (
|
||||
<View style={{ paddingTop: 16 }}>
|
||||
{[1,2,3,4].map((i) => <SkeletonCard key={i} />)}
|
||||
</View>
|
||||
) : (
|
||||
<FlatList
|
||||
data={data ?? []}
|
||||
keyExtractor={(item) => item.id}
|
||||
contentContainerStyle={styles.list}
|
||||
initialNumToRender={10}
|
||||
maxToRenderPerBatch={10}
|
||||
windowSize={5}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={isRefetching} onRefresh={refetch} tintColor="#003B7E" />
|
||||
<RefreshControl refreshing={isRefetching} onRefresh={refetch} tintColor="#003B7E" progressViewOffset={50} />
|
||||
}
|
||||
renderItem={({ item }) => (
|
||||
<NewsCard
|
||||
@@ -78,7 +121,7 @@ export default function NewsScreen() {
|
||||
/>
|
||||
)}
|
||||
ListEmptyComponent={
|
||||
<EmptyState icon="N" title="Keine News" subtitle="Noch keine Beitraege veroeffentlicht." />
|
||||
<EmptyState icon="newspaper-outline" title="Keine News" subtitle="Noch keine Beitraege veroeffentlicht." />
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user