feat: 新增任务详情页面及相关功能

- 创建任务详情页面,展示任务的详细信息,包括状态、描述、优先级和进度
- 实现任务完成和跳过功能,用户可通过按钮操作更新任务状态
- 添加评论功能,用户可以对任务进行评论并发送
- 优化任务卡片,点击后可跳转至任务详情页面
- 更新相关样式,确保界面一致性和美观性
This commit is contained in:
2025-08-23 13:33:39 +08:00
parent 75806df660
commit b807e498ed
5 changed files with 680 additions and 65 deletions

View File

@@ -5,6 +5,7 @@ import { useColorScheme } from '@/hooks/useColorScheme';
import { completeTask, skipTask } from '@/store/tasksSlice';
import { TaskListItem } from '@/types/goals';
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { useRouter } from 'expo-router';
import React from 'react';
import { Alert, Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
@@ -19,6 +20,7 @@ export const TaskCard: React.FC<TaskCardProps> = ({
const colorTokens = Colors[theme];
const dispatch = useAppDispatch();
const { showConfirm } = useGlobalDialog();
const router = useRouter();
const getStatusText = (status: string) => {
@@ -123,6 +125,10 @@ export const TaskCard: React.FC<TaskCardProps> = ({
);
};
const handleTaskPress = () => {
router.push(`/task-detail?taskId=${task.id}`);
};
const renderActionIcons = () => {
if (task.status === 'completed' || task.status === 'overdue' || task.status === 'skipped') {
return null;
@@ -158,7 +164,7 @@ export const TaskCard: React.FC<TaskCardProps> = ({
return (
<TouchableOpacity
style={[styles.container, { backgroundColor: colorTokens.background }]}
onPress={() => {}}
onPress={handleTaskPress}
activeOpacity={0.7}
>
{/* 头部区域 */}
@@ -205,23 +211,21 @@ export const TaskCard: React.FC<TaskCardProps> = ({
)}
{/* 进度百分比文本 */}
<View style={styles.progressTextContainer}>
<Text style={styles.progressText}>{Math.round(task.progressPercentage)}%</Text>
<Text style={styles.progressText}>{task.currentCount}/{task.targetCount}</Text>
</View>
</View>
{/* 底部信息 */}
<View style={styles.footer}>
<View style={styles.teamSection}>
{/* 模拟团队成员头像 */}
{/* 团队成员头像 */}
<View style={styles.avatars}>
<View style={[styles.avatar, { backgroundColor: '#FBBF24' }]}>
<Text style={styles.avatarText}>A</Text>
</View>
<View style={[styles.avatar, { backgroundColor: '#34D399' }]}>
<Text style={styles.avatarText}>B</Text>
</View>
<View style={[styles.avatar, { backgroundColor: '#60A5FA' }]}>
<Text style={styles.avatarText}>C</Text>
<View style={styles.avatar}>
<Image
source={require('@/assets/images/Sealife.jpeg')}
style={styles.avatarImage}
resizeMode="cover"
/>
</View>
</View>
</View>
@@ -395,17 +399,15 @@ const styles = StyleSheet.create({
avatar: {
width: 24,
height: 24,
borderRadius: 12,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 24,
marginRight: -8,
borderWidth: 2,
borderColor: '#FFFFFF',
overflow: 'hidden',
},
avatarText: {
fontSize: 10,
fontWeight: '600',
color: '#FFFFFF',
avatarImage: {
width: '100%',
height: '100%',
},
infoSection: {
flexDirection: 'row',

View File

@@ -22,8 +22,7 @@ export const TaskProgressCard: React.FC<TaskProgressCardProps> = ({
{/* 标题区域 */}
<View style={styles.header}>
<View style={styles.titleContainer}>
<Text style={styles.title}></Text>
<Text style={styles.subtitle}></Text>
<Text style={styles.title}></Text>
</View>
{headerButtons && (
<View style={styles.headerButtons}>
@@ -82,7 +81,7 @@ const styles = StyleSheet.create({
marginBottom: 20,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-start',
alignItems: 'center',
},
titleContainer: {
flex: 1,

View File

@@ -45,38 +45,6 @@ export function HeaderBar({
}
};
const getBackButtonStyle = () => {
const baseStyle = [styles.backButton];
switch (variant) {
case 'elevated':
return [...baseStyle, {
backgroundColor: `${theme.primary}15`, // 15% 透明度
borderWidth: 1,
borderColor: `${theme.primary}20`, // 20% 透明度
}];
case 'minimal':
return [...baseStyle, {
backgroundColor: `${theme.neutral100}80`, // 80% 透明度
}];
default:
return [...baseStyle, {
backgroundColor: `${theme.accentGreen}20`, // 20% 透明度
}];
}
};
const getBackButtonIconColor = () => {
switch (variant) {
case 'elevated':
return theme.primary;
case 'minimal':
return theme.textSecondary;
default:
return theme.onPrimary;
}
};
const getBorderStyle = () => {
if (!showBottomBorder) return {};
@@ -110,13 +78,13 @@ export function HeaderBar({
<TouchableOpacity
accessibilityRole="button"
onPress={onBack}
style={getBackButtonStyle()}
style={styles.backButton}
activeOpacity={0.7}
>
<Ionicons
name="chevron-back"
size={20}
color={getBackButtonIconColor()}
size={24}
color={theme.text}
/>
</TouchableOpacity>
) : (
@@ -157,17 +125,8 @@ const styles = StyleSheet.create({
backButton: {
width: 32,
height: 32,
borderRadius: 16,
alignItems: 'center',
justifyContent: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 2,
},
titleContainer: {
flex: 1,