feat: 增强任务管理功能,新增任务筛选和状态统计组件
- 在目标页面中集成任务筛选标签,支持按状态(全部、待完成、已完成)过滤任务 - 更新任务卡片,展示任务状态和优先级信息 - 新增任务进度卡片,统计各状态任务数量 - 优化空状态展示,根据筛选条件动态显示提示信息 - 引入新图标和图片资源,提升界面视觉效果
This commit is contained in:
175
components/TaskFilterTabs.tsx
Normal file
175
components/TaskFilterTabs.tsx
Normal file
@@ -0,0 +1,175 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
|
||||
export type TaskFilterType = 'all' | 'pending' | 'completed';
|
||||
|
||||
interface TaskFilterTabsProps {
|
||||
selectedFilter: TaskFilterType;
|
||||
onFilterChange: (filter: TaskFilterType) => void;
|
||||
taskCounts: {
|
||||
all: number;
|
||||
pending: number;
|
||||
completed: number;
|
||||
};
|
||||
}
|
||||
|
||||
export const TaskFilterTabs: React.FC<TaskFilterTabsProps> = ({
|
||||
selectedFilter,
|
||||
onFilterChange,
|
||||
taskCounts,
|
||||
}) => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.tabContainer}>
|
||||
{/* 全部 Tab */}
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.tab,
|
||||
selectedFilter === 'all' && styles.activeTab
|
||||
]}
|
||||
onPress={() => onFilterChange('all')}
|
||||
>
|
||||
<Text style={[
|
||||
styles.tabText,
|
||||
selectedFilter === 'all' && styles.activeTabText
|
||||
]}>
|
||||
全部
|
||||
</Text>
|
||||
<View style={[
|
||||
styles.badge,
|
||||
selectedFilter === 'all' ? styles.activeBadge : styles.inactiveBadge
|
||||
]}>
|
||||
<Text style={[
|
||||
styles.badgeText,
|
||||
selectedFilter === 'all' && styles.activeBadgeText
|
||||
]}>
|
||||
{taskCounts.all}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* 待完成 Tab */}
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.tab,
|
||||
selectedFilter === 'pending' && styles.activeTab
|
||||
]}
|
||||
onPress={() => onFilterChange('pending')}
|
||||
>
|
||||
<Text style={[
|
||||
styles.tabText,
|
||||
selectedFilter === 'pending' && styles.activeTabText
|
||||
]}>
|
||||
待完成
|
||||
</Text>
|
||||
<View style={[
|
||||
styles.badge,
|
||||
selectedFilter === 'pending' ? styles.activeBadge : styles.inactiveBadge
|
||||
]}>
|
||||
<Text style={[
|
||||
styles.badgeText,
|
||||
selectedFilter === 'pending' && styles.activeBadgeText
|
||||
]}>
|
||||
{taskCounts.pending}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* 已完成 Tab */}
|
||||
<TouchableOpacity
|
||||
style={[
|
||||
styles.tab,
|
||||
selectedFilter === 'completed' && styles.activeTab
|
||||
]}
|
||||
onPress={() => onFilterChange('completed')}
|
||||
>
|
||||
<Text style={[
|
||||
styles.tabText,
|
||||
selectedFilter === 'completed' && styles.activeTabText
|
||||
]}>
|
||||
已完成
|
||||
</Text>
|
||||
<View style={[
|
||||
styles.badge,
|
||||
selectedFilter === 'completed' ? styles.activeBadge : styles.inactiveBadge
|
||||
]}>
|
||||
<Text style={[
|
||||
styles.badgeText,
|
||||
selectedFilter === 'completed' && styles.activeBadgeText
|
||||
]}>
|
||||
{taskCounts.completed}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
paddingHorizontal: 20,
|
||||
},
|
||||
tabContainer: {
|
||||
backgroundColor: '#FFFFFF',
|
||||
borderRadius: 24,
|
||||
padding: 4,
|
||||
flexDirection: 'row',
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 1 },
|
||||
shadowOpacity: 0.05,
|
||||
shadowRadius: 2,
|
||||
elevation: 1,
|
||||
borderWidth: 1,
|
||||
borderColor: '#E5E7EB',
|
||||
},
|
||||
tab: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 12,
|
||||
borderRadius: 20,
|
||||
gap: 6,
|
||||
},
|
||||
activeTab: {
|
||||
backgroundColor: '#7A5AF8',
|
||||
shadowColor: '#7A5AF8',
|
||||
shadowOffset: { width: 0, height: 2 },
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 4,
|
||||
elevation: 3,
|
||||
},
|
||||
tabText: {
|
||||
fontSize: 14,
|
||||
fontWeight: '500',
|
||||
color: '#374151',
|
||||
},
|
||||
activeTabText: {
|
||||
color: '#FFFFFF',
|
||||
fontWeight: '600',
|
||||
},
|
||||
badge: {
|
||||
minWidth: 20,
|
||||
height: 20,
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 6,
|
||||
},
|
||||
inactiveBadge: {
|
||||
backgroundColor: '#E5E7EB',
|
||||
},
|
||||
activeBadge: {
|
||||
backgroundColor: '#EF4444',
|
||||
},
|
||||
badgeText: {
|
||||
fontSize: 12,
|
||||
fontWeight: '600',
|
||||
color: '#374151',
|
||||
},
|
||||
activeBadgeText: {
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user