- 将目标创建成功后的提示从系统默认的 Alert.alert 改为使用自定义确认弹窗,提升用户体验和视觉一致性 - 在任务筛选中新增“已跳过”选项,支持用户更好地管理任务状态 - 更新任务卡片和进度卡片,展示跳过任务的数量和状态 - 调整相关组件样式,确保界面一致性和美观性 - 编写相关文档,详细描述新功能和使用方法
140 lines
3.6 KiB
TypeScript
140 lines
3.6 KiB
TypeScript
import { TaskListItem } from '@/types/goals';
|
|
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
|
import React, { ReactNode } from 'react';
|
|
import { StyleSheet, Text, View } from 'react-native';
|
|
|
|
interface TaskProgressCardProps {
|
|
tasks: TaskListItem[];
|
|
headerButtons?: ReactNode;
|
|
}
|
|
|
|
export const TaskProgressCard: React.FC<TaskProgressCardProps> = ({
|
|
tasks,
|
|
headerButtons,
|
|
}) => {
|
|
// 计算各状态的任务数量
|
|
const pendingTasks = tasks.filter(task => task.status === 'pending');
|
|
const completedTasks = tasks.filter(task => task.status === 'completed');
|
|
const skippedTasks = tasks.filter(task => task.status === 'skipped');
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
{/* 标题区域 */}
|
|
<View style={styles.header}>
|
|
<View style={styles.titleContainer}>
|
|
<Text style={styles.title}>任务状态统计</Text>
|
|
<Text style={styles.subtitle}>各状态任务数量分布</Text>
|
|
</View>
|
|
{headerButtons && (
|
|
<View style={styles.headerButtons}>
|
|
{headerButtons}
|
|
</View>
|
|
)}
|
|
</View>
|
|
|
|
{/* 状态卡片区域 */}
|
|
<View style={styles.statusCards}>
|
|
{/* 待完成 卡片 */}
|
|
<View style={styles.statusCard}>
|
|
<View style={styles.cardHeader}>
|
|
<MaterialIcons name="pending" size={16} color="#7A5AF8" />
|
|
<Text style={styles.cardLabel} numberOfLines={1}>待完成</Text>
|
|
</View>
|
|
<Text style={styles.cardCount}>{pendingTasks.length}</Text>
|
|
</View>
|
|
|
|
{/* 已完成 卡片 */}
|
|
<View style={styles.statusCard}>
|
|
<View style={styles.cardHeader}>
|
|
<MaterialIcons name="check-circle" size={16} color="#10B981" />
|
|
<Text style={styles.cardLabel} numberOfLines={1}>已完成</Text>
|
|
</View>
|
|
<Text style={styles.cardCount}>{completedTasks.length}</Text>
|
|
</View>
|
|
|
|
{/* 已跳过 卡片 */}
|
|
<View style={styles.statusCard}>
|
|
<View style={styles.cardHeader}>
|
|
<MaterialIcons name="skip-next" size={16} color="#F59E0B" />
|
|
<Text style={styles.cardLabel} numberOfLines={1}>已跳过</Text>
|
|
</View>
|
|
<Text style={styles.cardCount}>{skippedTasks.length}</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
backgroundColor: '#FFFFFF',
|
|
borderRadius: 16,
|
|
padding: 20,
|
|
marginHorizontal: 20,
|
|
marginBottom: 20,
|
|
shadowColor: '#000',
|
|
shadowOffset: { width: 0, height: 2 },
|
|
shadowOpacity: 0.1,
|
|
shadowRadius: 8,
|
|
elevation: 4,
|
|
},
|
|
header: {
|
|
marginBottom: 20,
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'flex-start',
|
|
},
|
|
titleContainer: {
|
|
flex: 1,
|
|
},
|
|
headerButtons: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: 8,
|
|
},
|
|
title: {
|
|
fontSize: 20,
|
|
fontWeight: '700',
|
|
color: '#1F2937',
|
|
marginBottom: 4,
|
|
},
|
|
subtitle: {
|
|
fontSize: 14,
|
|
color: '#6B7280',
|
|
fontWeight: '400',
|
|
},
|
|
statusCards: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
gap: 8,
|
|
},
|
|
statusCard: {
|
|
flex: 1,
|
|
backgroundColor: '#FFFFFF',
|
|
borderRadius: 12,
|
|
padding: 12,
|
|
borderWidth: 1,
|
|
borderColor: '#E5E7EB',
|
|
alignItems: 'flex-start',
|
|
minHeight: 80,
|
|
},
|
|
cardHeader: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
marginBottom: 8,
|
|
gap: 6,
|
|
flexWrap: 'wrap',
|
|
},
|
|
cardLabel: {
|
|
fontSize: 11,
|
|
fontWeight: '500',
|
|
color: '#1F2937',
|
|
lineHeight: 14,
|
|
},
|
|
cardCount: {
|
|
fontSize: 24,
|
|
fontWeight: '700',
|
|
color: '#1F2937',
|
|
},
|
|
});
|