feat: 新增目标管理功能及相关组件
- 创建目标管理演示页面,展示高保真的目标管理界面 - 实现待办事项卡片的横向滑动展示,支持时间筛选功能 - 新增时间轴组件,展示选中日期的具体任务 - 更新底部导航,添加目标管理和演示页面的路由 - 优化个人页面菜单项,提供目标管理的快速访问 - 编写目标管理功能实现文档,详细描述功能和组件架构
This commit is contained in:
105
components/TodoCarousel.tsx
Normal file
105
components/TodoCarousel.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import { Colors } from '@/constants/Colors';
|
||||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||||
import React, { useRef } from 'react';
|
||||
import { Dimensions, ScrollView, StyleSheet, Text, View } from 'react-native';
|
||||
import { TodoCard, TodoItem } from './TodoCard';
|
||||
|
||||
interface TodoCarouselProps {
|
||||
todos: TodoItem[];
|
||||
onTodoPress?: (item: TodoItem) => void;
|
||||
onToggleComplete?: (item: TodoItem) => void;
|
||||
}
|
||||
|
||||
const { width: screenWidth } = Dimensions.get('window');
|
||||
|
||||
export function TodoCarousel({ todos, onTodoPress, onToggleComplete }: TodoCarouselProps) {
|
||||
const theme = useColorScheme() ?? 'light';
|
||||
const colorTokens = Colors[theme];
|
||||
const scrollViewRef = useRef<ScrollView>(null);
|
||||
|
||||
if (!todos || todos.length === 0) {
|
||||
return (
|
||||
<View style={styles.emptyContainer}>
|
||||
<Text style={[styles.emptyText, { color: colorTokens.textMuted }]}>
|
||||
今天暂无待办事项
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView
|
||||
ref={scrollViewRef}
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
snapToInterval={(screenWidth - 60) * 0.65 + 16} // 卡片宽度 + 间距
|
||||
snapToAlignment="start"
|
||||
decelerationRate="fast"
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
style={styles.scrollView}
|
||||
>
|
||||
{todos.map((item, index) => (
|
||||
<TodoCard
|
||||
key={item.id}
|
||||
item={item}
|
||||
onPress={onTodoPress}
|
||||
onToggleComplete={onToggleComplete}
|
||||
/>
|
||||
))}
|
||||
{/* 占位符,确保最后一张卡片有足够的滑动空间 */}
|
||||
<View style={{ width: 20 }} />
|
||||
</ScrollView>
|
||||
|
||||
{/* 底部指示器 */}
|
||||
<View style={styles.indicatorContainer}>
|
||||
{todos.map((_, index) => (
|
||||
<View
|
||||
key={index}
|
||||
style={[
|
||||
styles.indicator,
|
||||
{ backgroundColor: index === 0 ? colorTokens.primary : colorTokens.border }
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
},
|
||||
scrollView: {
|
||||
marginBottom: 12,
|
||||
},
|
||||
scrollContent: {
|
||||
paddingHorizontal: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
emptyContainer: {
|
||||
height: 140,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginHorizontal: 20,
|
||||
borderRadius: 20,
|
||||
borderWidth: 1,
|
||||
borderColor: '#E5E7EB',
|
||||
borderStyle: 'dashed',
|
||||
},
|
||||
emptyText: {
|
||||
fontSize: 14,
|
||||
fontWeight: '500',
|
||||
},
|
||||
indicatorContainer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
gap: 6,
|
||||
},
|
||||
indicator: {
|
||||
width: 6,
|
||||
height: 6,
|
||||
borderRadius: 3,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user