import { Ionicons } from '@expo/vector-icons'; import { useRouter } from 'expo-router'; import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useNotifications } from '../src/hooks'; import { LoadingState, ErrorState, EmptyState } from '../src/components/StateView'; import { colors, spacing } from '../src/theme'; import type { Notification } from '../src/types'; const TYPE_ICON: Record = { offer: 'gift-outline', system: 'information-circle-outline', promotion: 'megaphone-outline', }; /** * 通知收件箱:列表 + 标记已读 + 全部已读。 * 来自后端 /notifications(STUDENT 旗下);点击单条标记已读。 */ export default function NotificationsScreen() { const router = useRouter(); const { items, loading, error, refresh, isEmpty, markRead, markAllRead } = useNotifications(); const hasUnread = items.some((n) => !n.read); return ( router.back()} hitSlop={8}> 通知 {hasUnread ? ( 全部已读 ) : ( )} {loading ? ( ) : error ? ( ) : isEmpty ? ( ) : ( {items.map((n) => ( markRead(n.id)} hitSlop={4} > {n.title} {!n.read && } {n.content} {n.timestamp} ))} )} ); } const styles = StyleSheet.create({ safeArea: { flex: 1, backgroundColor: colors.pageBg, }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: spacing.card, height: 48, backgroundColor: colors.white, borderBottomWidth: 1, borderBottomColor: colors.borderLight, }, headerBtn: { width: 40, height: 40, alignItems: 'center', justifyContent: 'center', }, headerTitle: { fontSize: 17, fontWeight: '700', color: colors.textPrimary, }, markAllBtn: { paddingHorizontal: 8, height: 32, alignItems: 'center', justifyContent: 'center', }, markAllText: { fontSize: 13, fontWeight: '600', color: colors.primary, }, scroll: { flex: 1, }, content: { paddingHorizontal: spacing.card, paddingTop: 12, paddingBottom: 24, }, card: { flexDirection: 'row', backgroundColor: colors.white, borderRadius: 8, padding: spacing.card, marginBottom: spacing.card, }, cardUnread: { backgroundColor: colors.primaryLight, }, iconWrap: { width: 36, height: 36, borderRadius: 18, backgroundColor: colors.pageBg, alignItems: 'center', justifyContent: 'center', marginRight: spacing.card, }, iconWrapUnread: { backgroundColor: colors.white, }, cardBody: { flex: 1, }, cardTop: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', }, cardTitle: { fontSize: 15, fontWeight: '600', color: colors.textPrimary, }, dot: { width: 8, height: 8, borderRadius: 4, backgroundColor: colors.primary, }, cardContent: { fontSize: 13, color: colors.textSecondary, marginTop: 4, lineHeight: 18, }, cardTime: { fontSize: 12, color: colors.textHint, marginTop: 6, }, });