expo-duooomi-app/app/(tabs)/message.tsx

220 lines
6.1 KiB
TypeScript

import { LinearGradient } from 'expo-linear-gradient'
import { StatusBar } from 'expo-status-bar'
import { useEffect, useState } from 'react'
import { Pressable, ScrollView, StatusBar as RNStatusBar, StyleSheet, Text, View } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import { useActivities } from '@/hooks/data/use-activities'
type MessageType = 'all' | 'notice' | 'other'
export default function MessageScreen() {
const [activeTab, setActiveTab] = useState<MessageType>('all')
const { load, loading, error, data } = useActivities()
useEffect(() => {
load({ page: 1, limit: 20, orderBy: 'createdAt', order: 'desc' })
}, [])
const activities = data?.activities || []
const filteredActivities = activities.filter((activity) => {
if (activeTab === 'all') return true
return activeTab === 'notice'
})
return (
<SafeAreaView edges={['top']} style={styles.container}>
<StatusBar style="light" />
<RNStatusBar barStyle="light-content" />
{/* 固定在顶部的标签选择器 */}
<View style={styles.segment}>
<Pressable onPress={() => setActiveTab('all')}>
{activeTab === 'all' ? (
<View style={styles.segmentTextActiveWrapper}>
<LinearGradient
colors={['#FF9966', '#FF6699', '#9966FF']}
end={{ x: 1, y: 0 }}
start={{ x: 0, y: 0 }}
style={styles.segmentTextActiveBg}
/>
<Text style={[styles.segmentText, styles.segmentTextActiveText]}></Text>
</View>
) : (
<Text style={styles.segmentText}></Text>
)}
</Pressable>
<Pressable onPress={() => setActiveTab('notice')}>
{activeTab === 'notice' ? (
<View style={styles.segmentTextActiveWrapper}>
<LinearGradient
colors={['#FF9966', '#FF6699', '#9966FF']}
end={{ x: 1, y: 0 }}
start={{ x: 0, y: 0 }}
style={styles.segmentTextActiveBg}
/>
<Text style={[styles.segmentText, styles.segmentTextActiveText]}></Text>
</View>
) : (
<Text style={styles.segmentText}></Text>
)}
</Pressable>
<Pressable onPress={() => setActiveTab('other')}>
{activeTab === 'other' ? (
<View style={styles.segmentTextActiveWrapper}>
<LinearGradient
colors={['#FF9966', '#FF6699', '#9966FF']}
end={{ x: 1, y: 0 }}
start={{ x: 0, y: 0 }}
style={styles.segmentTextActiveBg}
/>
<Text style={[styles.segmentText, styles.segmentTextActiveText]}></Text>
</View>
) : (
<Text style={styles.segmentText}></Text>
)}
</Pressable>
</View>
<ScrollView
contentContainerStyle={styles.scrollContent}
showsVerticalScrollIndicator={false}
style={styles.scrollView}
>
{loading ? (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>...</Text>
</View>
) : error ? (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}></Text>
</View>
) : filteredActivities.length > 0 ? (
filteredActivities.map((activity) => (
<View key={activity.id} style={styles.cardContainer}>
<Text style={styles.cardTitle}>{activity.title}</Text>
<Text numberOfLines={2} style={styles.cardSubtitle}>
{activity.titleEn || activity.desc}
</Text>
<View style={styles.cardBody}>
<Text style={styles.cardBodyText}>{activity.desc}</Text>
</View>
<Text style={styles.cardTime}>
{new Date(activity.createdAt)
.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
})
.replace(/\//g, '-')}
</Text>
</View>
))
) : (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>💭</Text>
<Text style={styles.emptyText}></Text>
</View>
)}
</ScrollView>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#090A0B',
},
scrollView: {
flex: 1,
backgroundColor: '#090A0B',
},
scrollContent: {
paddingHorizontal: 4,
paddingTop: 12,
paddingBottom: 24,
},
segment: {
flexDirection: 'row',
paddingHorizontal: 8,
paddingTop: 19,
paddingBottom: 12,
backgroundColor: '#090A0B',
gap: 16,
},
segmentText: {
fontSize: 14,
color: '#FFFFFF',
},
segmentTextActiveWrapper: {
position: 'relative',
paddingBottom: 2,
justifyContent: 'flex-end',
alignSelf: 'flex-start',
},
segmentTextActiveBg: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: 10,
backgroundColor: '#FF9966',
},
segmentTextActiveText: {
zIndex: 1,
},
cardContainer: {
backgroundColor: '#16181B',
borderRadius: 16,
padding: 16,
marginBottom: 12,
marginHorizontal: 4,
},
cardTitle: {
color: '#FFFFFF',
fontSize: 15,
fontWeight: '600',
marginBottom: 8,
},
cardSubtitle: {
color: '#ABABAB',
fontSize: 11,
marginBottom: 16,
},
cardBody: {
backgroundColor: '#26292E',
borderRadius: 12,
height: 100,
marginBottom: 12,
},
cardBodyText: {
color: '#FFFFFF',
fontSize: 12,
opacity: 0.8,
},
cardTime: {
color: '#8A8A8A',
fontSize: 10,
},
emptyContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: 200,
},
emptyText: {
color: '#8A8A8A',
fontSize: 12,
marginTop: 16,
},
})