- 将目标页面改为任务列表,支持任务的创建、完成和跳过功能 - 新增任务卡片和任务进度卡片组件,展示任务状态和进度 - 实现任务数据的获取和管理,集成Redux状态管理 - 更新API服务,支持任务相关的CRUD操作 - 编写任务管理功能实现文档,详细描述功能和组件架构
141 lines
3.5 KiB
TypeScript
141 lines
3.5 KiB
TypeScript
import { TaskListItem } from '@/types/goals';
|
||
import React from 'react';
|
||
import { StyleSheet, Text, View } from 'react-native';
|
||
|
||
interface TaskProgressCardProps {
|
||
tasks: TaskListItem[];
|
||
}
|
||
|
||
export const TaskProgressCard: React.FC<TaskProgressCardProps> = ({
|
||
tasks,
|
||
}) => {
|
||
// 计算今日任务完成进度
|
||
const todayTasks = tasks.filter(task => task.isToday);
|
||
const completedTodayTasks = todayTasks.filter(task => task.status === 'completed');
|
||
const progressPercentage = todayTasks.length > 0
|
||
? Math.round((completedTodayTasks.length / todayTasks.length) * 100)
|
||
: 0;
|
||
|
||
// 计算进度角度
|
||
const progressAngle = (progressPercentage / 100) * 360;
|
||
|
||
return (
|
||
<View style={styles.container}>
|
||
{/* 左侧内容 */}
|
||
<View style={styles.leftContent}>
|
||
<View style={styles.textContainer}>
|
||
<Text style={styles.title}>今日目标</Text>
|
||
<Text style={styles.subtitle}>加油,快完成啦!</Text>
|
||
</View>
|
||
|
||
</View>
|
||
|
||
{/* 右侧进度圆环 */}
|
||
<View style={styles.progressContainer}>
|
||
{/* 背景圆环 */}
|
||
<View style={[styles.progressCircle, styles.progressBackground]} />
|
||
|
||
{/* 进度圆环 */}
|
||
<View style={[styles.progressCircle, styles.progressFill]}>
|
||
<View
|
||
style={[
|
||
styles.progressArc,
|
||
{
|
||
width: 68,
|
||
height: 68,
|
||
borderRadius: 34,
|
||
borderWidth: 6,
|
||
borderColor: '#8B5CF6',
|
||
borderTopColor: progressAngle > 0 ? '#8B5CF6' : 'transparent',
|
||
borderRightColor: progressAngle > 90 ? '#8B5CF6' : 'transparent',
|
||
borderBottomColor: progressAngle > 180 ? '#8B5CF6' : 'transparent',
|
||
borderLeftColor: progressAngle > 270 ? '#8B5CF6' : 'transparent',
|
||
transform: [{ rotate: '-90deg' }],
|
||
},
|
||
]}
|
||
/>
|
||
</View>
|
||
|
||
{/* 进度文字 */}
|
||
<View style={styles.progressTextContainer}>
|
||
<Text style={styles.progressText}>{progressPercentage}%</Text>
|
||
</View>
|
||
</View>
|
||
|
||
</View>
|
||
);
|
||
};
|
||
|
||
const styles = StyleSheet.create({
|
||
container: {
|
||
backgroundColor: '#8B5CF6',
|
||
borderRadius: 16,
|
||
padding: 20,
|
||
marginHorizontal: 20,
|
||
marginBottom: 20,
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
position: 'relative',
|
||
shadowColor: '#8B5CF6',
|
||
shadowOffset: { width: 0, height: 4 },
|
||
shadowOpacity: 0.3,
|
||
shadowRadius: 8,
|
||
elevation: 8,
|
||
},
|
||
leftContent: {
|
||
flex: 1,
|
||
marginRight: 20,
|
||
},
|
||
textContainer: {
|
||
marginBottom: 16,
|
||
},
|
||
title: {
|
||
color: '#FFFFFF',
|
||
fontSize: 16,
|
||
fontWeight: '600',
|
||
marginBottom: 2,
|
||
},
|
||
subtitle: {
|
||
color: '#FFFFFF',
|
||
fontSize: 14,
|
||
fontWeight: '400',
|
||
opacity: 0.9,
|
||
},
|
||
progressContainer: {
|
||
width: 80,
|
||
height: 80,
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
position: 'relative',
|
||
},
|
||
progressCircle: {
|
||
position: 'absolute',
|
||
width: 80,
|
||
height: 80,
|
||
borderRadius: 40,
|
||
},
|
||
progressBackground: {
|
||
borderWidth: 6,
|
||
borderColor: 'rgba(255, 255, 255, 0.3)',
|
||
},
|
||
progressFill: {
|
||
borderWidth: 6,
|
||
borderColor: 'transparent',
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
},
|
||
progressArc: {
|
||
position: 'absolute',
|
||
},
|
||
progressTextContainer: {
|
||
position: 'absolute',
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
},
|
||
progressText: {
|
||
color: '#FFFFFF',
|
||
fontSize: 16,
|
||
fontWeight: '700',
|
||
},
|
||
});
|