import { DateSelector } from '@/components/DateSelector'; import { TaskCard } from '@/components/TaskCard'; import { HeaderBar } from '@/components/ui/HeaderBar'; import { Colors } from '@/constants/Colors'; import { TAB_BAR_BOTTOM_OFFSET, TAB_BAR_HEIGHT } from '@/constants/TabBar'; import { useColorScheme } from '@/hooks/useColorScheme'; import { tasksApi } from '@/services/tasksApi'; import { TaskListItem } from '@/types/goals'; import { getTodayIndexInMonth } from '@/utils/date'; import { useFocusEffect } from '@react-navigation/native'; import dayjs from 'dayjs'; import { LinearGradient } from 'expo-linear-gradient'; import { useRouter } from 'expo-router'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Alert, FlatList, RefreshControl, StatusBar, StyleSheet, Text, View } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; export default function GoalsDetailScreen() { const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; const colorTokens = Colors[theme]; const router = useRouter(); // 本地状态管理 const [tasks, setTasks] = useState([]); const [tasksLoading, setTasksLoading] = useState(false); const [tasksError, setTasksError] = useState(null); const [selectedDate, setSelectedDate] = useState(new Date()); const [refreshing, setRefreshing] = useState(false); // 日期选择器相关状态 const [selectedIndex, setSelectedIndex] = useState(getTodayIndexInMonth()); // 加载任务列表 const loadTasks = async (targetDate?: Date) => { try { setTasksLoading(true); setTasksError(null); const dateToUse = targetDate || selectedDate; console.log('Loading tasks for date:', dayjs(dateToUse).format('YYYY-MM-DD')); const response = await tasksApi.getTasks({ startDate: dayjs(dateToUse).startOf('day').toISOString(), endDate: dayjs(dateToUse).endOf('day').toISOString(), }); console.log('Tasks API response:', response); setTasks(response.list || []); } catch (error: any) { console.error('Failed to load tasks:', error); setTasksError(error.message || '获取任务列表失败'); setTasks([]); } finally { setTasksLoading(false); } }; // 页面聚焦时重新加载数据 useFocusEffect( useCallback(() => { console.log('useFocusEffect - loading tasks'); loadTasks(); }, []) ); // 下拉刷新 const onRefresh = async () => { setRefreshing(true); try { await loadTasks(); } finally { setRefreshing(false); } }; // 处理错误提示 useEffect(() => { if (tasksError) { Alert.alert('错误', tasksError); setTasksError(null); } }, [tasksError]); // 日期选择处理 const onSelectDate = async (index: number, date: Date) => { console.log('Date selected:', dayjs(date).format('YYYY-MM-DD')); setSelectedIndex(index); setSelectedDate(date); // 重新加载对应日期的任务数据 await loadTasks(date); }; // 根据选中日期筛选任务,并将已完成的任务放到最后 const filteredTasks = useMemo(() => { const selected = dayjs(selectedDate); const filtered = tasks.filter(task => { if (task.status === 'skipped') return false; const taskDate = dayjs(task.startDate); return taskDate.isSame(selected, 'day'); }); // 对筛选结果进行排序:已完成的任务放到最后 return [...filtered].sort((a, b) => { const aCompleted = a.status === 'completed'; const bCompleted = b.status === 'completed'; // 如果a已完成而b未完成,a排在后面 if (aCompleted && !bCompleted) { return 1; } // 如果b已完成而a未完成,b排在后面 if (bCompleted && !aCompleted) { return -1; } // 如果都已完成或都未完成,保持原有顺序 return 0; }); }, [selectedDate, tasks]); const handleBackPress = () => { router.back(); }; // 渲染任务项 const renderTaskItem = ({ item }: { item: TaskListItem }) => ( ); // 渲染空状态 const renderEmptyState = () => { const selectedDateStr = dayjs(selectedDate).format('YYYY年M月D日'); if (tasksLoading) { return ( 加载中... ); } return ( 暂无任务 {selectedDateStr} 没有任务安排 ); }; return ( {/* 背景渐变 */} {/* 装饰性圆圈 */} {/* 标题区域 */} {/* 日期选择器 */} {/* 任务列表 */} item.id} contentContainerStyle={styles.taskList} showsVerticalScrollIndicator={false} refreshControl={ } ListEmptyComponent={renderEmptyState} /> ); } const styles = StyleSheet.create({ container: { flex: 1, }, gradientBackground: { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, opacity: 0.6, }, decorativeCircle1: { position: 'absolute', top: -20, right: -20, width: 60, height: 60, borderRadius: 30, backgroundColor: '#0EA5E9', opacity: 0.1, }, decorativeCircle2: { position: 'absolute', bottom: -15, left: -15, width: 40, height: 40, borderRadius: 20, backgroundColor: '#0EA5E9', opacity: 0.05, }, content: { flex: 1, }, // 日期选择器样式 dateSelector: { paddingHorizontal: 20, }, taskListContainer: { flex: 1, borderTopLeftRadius: 24, borderTopRightRadius: 24, overflow: 'hidden', }, taskList: { paddingHorizontal: 20, paddingBottom: TAB_BAR_HEIGHT + TAB_BAR_BOTTOM_OFFSET + 20, }, emptyState: { alignItems: 'center', justifyContent: 'center', paddingVertical: 60, }, emptyStateTitle: { fontSize: 18, fontWeight: '600', marginBottom: 8, }, emptyStateSubtitle: { fontSize: 14, textAlign: 'center', lineHeight: 20, }, });