今天我們來稍微改進我們的首頁。首先創建Task的type。
src\types\index.ts
export type Task = {
id: string;
title: string;
startDate: string | null;
endDate: string | null;
description: string;
isDone: boolean;
tags: Tags[];
subTasks: Task[];
}
export type Tags = {
title: string;
}
我們這裡創建隨機生成的generateRandomTasks函數。
const generateRandomTasks = (count: number): Task[] => {
const generateRandomDate = (start: Date, end: Date) => {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())).toISOString().split('T')[0];
};
const possibleTags: Tags[] = [
{ title: '工作' },
{ title: '個人' },
{ title: '學習' },
{ title: '娛樂' },
];
const tasks: Task[] = [];
for (let i = 0; i < count; i++) {
const startDate = generateRandomDate(new Date(), new Date(Date.now() + 30 * 24 * 60 * 60 * 1000));
const endDate = generateRandomDate(new Date(startDate), new Date(Date.now() + 60 * 24 * 60 * 60 * 1000));
tasks.push({
id: `task-${i + 1}`,
title: `任務 ${i + 1}`,
startDate,
endDate,
description: `隨機生成的第 ${i + 1} 筆內容。`,
isDone: Math.random() < 0.3,
tags: possibleTags.filter(() => Math.random() < 0.3),
subTasks: [],
});
}
return tasks;
};
我們使用FlatList來呈現我們的任務列表,並且透過TouchableOpacity以及style來創建我們的checkbox。
接著我們完成我們的頁面src\pages\home.page.tsx
,我們這裡先創建50筆:
import React, { useState } from 'react';
import { View, Text, TextInput, FlatList, StyleSheet, TouchableOpacity } from 'react-native';
import { Colors } from 'react-native/Libraries/NewAppScreen';
import { Task, Tags } from '../types';
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 10,
},
title: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 10,
},
searchBar: {
height: 40,
borderColor: 'gray',
borderWidth: 1,
borderRadius: 5,
paddingHorizontal: 10,
marginBottom: 10,
},
taskList: {
flex: 1,
},
taskItem: {
flexDirection: 'row',
alignItems: 'center',
padding: 10,
borderBottomWidth: 1,
borderBottomColor: '#ccc',
},
checkbox: {
width: 24,
height: 24,
borderWidth: 2,
borderColor: '#007AFF',
borderRadius: 12,
marginRight: 10,
justifyContent: 'center',
alignItems: 'center',
},
checkboxInner: {
width: 12,
height: 12,
borderRadius: 6,
backgroundColor: '#007AFF',
},
taskContent: {
flex: 1,
},
taskTitle: {
fontSize: 16,
fontWeight: 'bold',
},
taskDates: {
fontSize: 12,
color: '#666',
},
taskDescription: {
fontSize: 14,
marginTop: 5,
},
taskTags: {
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: 5,
},
tag: {
backgroundColor: '#E0E0E0',
borderRadius: 10,
padding: 5,
marginRight: 5,
marginBottom: 5,
},
tagText: {
fontSize: 12,
},
});
type HomePageProps = {
isDarkMode?: boolean;
};
const generateRandomTasks = (count: number): Task[] => {
const generateRandomDate = (start: Date, end: Date) => {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())).toISOString().split('T')[0];
};
const possibleTags: Tags[] = [
{ title: '工作' },
{ title: '個人' },
{ title: '學習' },
{ title: '娛樂' },
];
const tasks: Task[] = [];
for (let i = 0; i < count; i++) {
const startDate = generateRandomDate(new Date(), new Date(Date.now() + 30 * 24 * 60 * 60 * 1000));
const endDate = generateRandomDate(new Date(startDate), new Date(Date.now() + 60 * 24 * 60 * 60 * 1000));
tasks.push({
id: `task-${i + 1}`,
title: `任務 ${i + 1}`,
startDate,
endDate,
description: `隨機生成的第 ${i + 1} 筆內容。`,
isDone: Math.random() < 0.3,
tags: possibleTags.filter(() => Math.random() < 0.3),
subTasks: [],
});
}
return tasks;
};
const HomePage: React.FC<HomePageProps> = ({ isDarkMode = false }) => {
const [tasks, setTasks] = useState<Task[]>(generateRandomTasks(50));
const toggleTaskStatus = (id: string) => {
setTasks(prevTasks =>
prevTasks.map(task =>
task.id === id ? { ...task, isDone: !task.isDone } : task
)
);
};
const renderTask = ({ item }: { item: Task }) => (
<View
style={[
styles.taskItem,
{ backgroundColor: item.isDone ? '#E8F5E9' : 'transparent' }
]}
>
<TouchableOpacity onPress={() => toggleTaskStatus(item.id)}>
<View style={styles.checkbox}>
{item.isDone && <View style={styles.checkboxInner} />}
</View>
</TouchableOpacity>![https://ithelp.ithome.com.tw/upload/images/20240923/20108931TbGiOFWbV6.png](https://ithelp.ithome.com.tw/upload/images/20240923/20108931TbGiOFWbV6.png)
<View style={styles.taskContent}>
<Text style={styles.taskTitle}>{item.title}</Text>
<Text style={styles.taskDates}>
{item.startDate} - {item.endDate}
</Text>
<Text style={styles.taskDescription}>{item.description}</Text>
<View style={styles.taskTags}>
{item.tags.map((tag, index) => (
<View key={index} style={styles.tag}>
<Text style={styles.tagText}>{tag.title}</Text>
</View>
))}
</View>
</View>
</View>
);
return (
<View style={styles.container}>
<Text style={styles.title}>任務列表</Text>
<TextInput
style={styles.searchBar}
placeholder="搜尋欄"
placeholderTextColor={isDarkMode ? Colors.light : Colors.dark}
/>
<FlatList
style={styles.taskList}
data={tasks}
renderItem={renderTask}
keyExtractor={item => item.id}
/>
</View>
);
};
export default HomePage;
今天先簡易的修改一下首頁,明天會接續完成其他的頁面部分,並且引進狀態管理套件。