今天來調整設定頁面,並且創建使用者頁面。然後修改bottom下方的按鈕。
首先我們先創建使用者的類型和狀態。
// 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;
}
export type User = {
id: string;
username: string;
email: string;
avatar?: string;
createdAt: string;
};
// src/stores/atoms.ts
import { atom } from 'jotai';
import { Task, User } from '../types';
export const userAtom = atom<User | null>(null);
export const tasksAtom = atom<Task[]>([]);
接著調整App下方頁面修改,修改我們的bottom和初始一個假的user
import React, { useEffect, useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, StatusBar, useColorScheme } from 'react-native';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { Colors } from 'react-native/Libraries/NewAppScreen';
import HomePage from './src/pages/home.page';
import AddTaskPage from './src/pages/add-task.page';
import StatisticsPage from './src/pages/statistics-page';
import SettingsPage from './src/pages/settings.page';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import TaskDetailsPage from './src/pages/task-detail.page';
import { Tags, Task } from './src/types';
import { useAtom } from 'jotai';
import { userAtom } from './src/stores/atoms';
import UserPage from './src/pages/user.page';
function MainContent() {
const [isDarkMode, setIsDarkMode] = useState(useColorScheme() === 'dark');
const [currentPage, setCurrentPage] = useState('home');
const [tasks, setTasks] = useState<Task[]>([]);
const [selectedTask, setSelectedTask] = useState<Task | null>(null);
const [user, setUser] = useAtom(userAtom);
useEffect(() => {
// 生成隨機任務當應用啟動時
setTasks(generateRandomTasks(10));
// 模擬用戶登入
setUser({
id: '1',
username: 'JohnDoe',
email: 'johndoe@example.com',
createdAt: new Date().toISOString(),
});
}, []);
const toggleDarkMode = () => {
setIsDarkMode(!isDarkMode);
};
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: '娛樂' },
];
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 renderPage = () => {
switch (currentPage) {
case 'home':
return (
<HomePage
isDarkMode={isDarkMode}
tasks={tasks}
setTasks={setTasks}
onTaskSelect={(task) => {
setSelectedTask(task);
setCurrentPage('taskDetails');
}}
/>
);
case 'add':
return <AddTaskPage isDarkMode={isDarkMode} />;
case 'stats':
return <StatisticsPage isDarkMode={isDarkMode} tasks={tasks} />;
case 'user':
return <UserPage navigation={{ navigate: setCurrentPage }} />;
case 'settings':
return <SettingsPage isDarkMode={isDarkMode} toggleDarkMode={toggleDarkMode} navigation={undefined} />;
case 'taskDetails':
return selectedTask ? (
<TaskDetailsPage
isDarkMode={isDarkMode}
task={selectedTask}
onBack={() => setCurrentPage('home')}
onTaskUpdate={(updatedTask) => {
setTasks(prevTasks =>
prevTasks.map(task =>
task.id === updatedTask.id ? updatedTask : task
)
);
setCurrentPage('home');
}}
onTaskDelete={(taskId) => {
setTasks(prevTasks => prevTasks.filter(task => task.id !== taskId));
setCurrentPage('home');
}}
/>
) : null;
default:
return <HomePage isDarkMode={isDarkMode} tasks={tasks} setTasks={setTasks} />;
}
};
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
flex: 1,
};
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<SafeAreaView style={backgroundStyle}>
<StatusBar
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
backgroundColor={backgroundStyle.backgroundColor}
/>
<View style={styles.topArea}>
<Text style={styles.topText}>我的應用</Text>
</View>
<View style={styles.container}>
{renderPage()}
</View>
<View style={styles.bottomNav}>
<TouchableOpacity style={styles.navItem} onPress={() => setCurrentPage('home')}>
<Text style={styles.navText}>主頁</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.navItem} onPress={() => setCurrentPage('add')}>
<Text style={styles.navText}>新增</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.navItem} onPress={() => setCurrentPage('stats')}>
<Text style={styles.navText}>統計</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.navItem} onPress={() => setCurrentPage('user')}>
<Text style={styles.navText}>用戶</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</GestureHandlerRootView>
);
}
function App(): React.JSX.Element {
return (
<SafeAreaProvider>
<MainContent />
</SafeAreaProvider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
topArea: {
height: 50,
justifyContent: 'center',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#ccc',
backgroundColor: '#f8f8f8',
},
topText: {
fontSize: 18,
fontWeight: 'bold',
},
bottomNav: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
height: 50,
borderTopWidth: 1,
borderTopColor: '#ccc',
backgroundColor: '#f8f8f8',
},
navItem: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
height: '100%',
},
navText: {
fontSize: 12,
},
});
export default App;
我們來創建User頁面
// src\pages\user.page.tsx
import React from 'react';
import { View, Text, StyleSheet, Image, TouchableOpacity, ScrollView } from 'react-native';
import { useAtom } from 'jotai';
import { userAtom } from '../stores/atoms';
type UserPageProps = {
navigation: any;
};
const UserPage: React.FC<UserPageProps> = ({ navigation }) => {
const [user] = useAtom(userAtom);
if (!user) {
return (
<View style={styles.container}>
<Text>請先登入</Text>
</View>
);
}
return (
<ScrollView style={styles.container}>
<View style={styles.profileHeader}>
<Image
source={{ uri: user.avatar || 'https://via.placeholder.com/150' }}
style={styles.avatar}
/>
<Text style={styles.username}>{user.username}</Text>
<Text style={styles.email}>{user.email}</Text>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>用戶信息</Text>
<View style={styles.infoItem}>
<Text style={styles.infoLabel}>ID:</Text>
<Text style={styles.infoValue}>{user.id}</Text>
</View>
<View style={styles.infoItem}>
<Text style={styles.infoLabel}>創建日期:</Text>
<Text style={styles.infoValue}>{new Date(user.createdAt).toLocaleDateString()}</Text>
</View>
</View>
<TouchableOpacity
style={styles.settingsButton}
onPress={() => navigation.navigate('Settings')}
>
<Text style={styles.settingsButtonText}>設置</Text>
</TouchableOpacity>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
},
profileHeader: {
alignItems: 'center',
marginBottom: 20,
},
avatar: {
width: 100,
height: 100,
borderRadius: 50,
marginBottom: 10,
},
username: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 5,
},
email: {
fontSize: 16,
color: '#666',
},
section: {
marginBottom: 20,
},
sectionTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 10,
},
infoItem: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 5,
},
infoLabel: {
fontWeight: 'bold',
},
infoValue: {
color: '#666',
},
settingsButton: {
backgroundColor: '#007AFF',
padding: 10,
borderRadius: 5,
alignItems: 'center',
},
settingsButtonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
});
export default UserPage;
接著,調整我們的設置頁面。
// src\pages\settings.page.tsx
import React from 'react';
import { View, Text, StyleSheet, Switch, TouchableOpacity, ScrollView } from 'react-native';
import { useAtom } from 'jotai';
import { userAtom } from '../stores/atoms';
type SettingsPageProps = {
isDarkMode: boolean;
toggleDarkMode: () => void;
navigation: any;
};
const SettingsPage: React.FC<SettingsPageProps> = ({ isDarkMode, toggleDarkMode, navigation }) => {
const [user] = useAtom(userAtom);
const [notifications, setNotifications] = React.useState(true);
const [autoSync, setAutoSync] = React.useState(true);
const handleLogout = () => {
console.log('User logged out');
// navigation.navigate('Login');
};
return (
<ScrollView style={styles.container}>
<Text style={styles.title}>設置</Text>
<View style={styles.section}>
<Text style={styles.sectionTitle}>應用設置</Text>
<View style={styles.settingItem}>
<Text style={styles.settingLabel}>深色模式</Text>
<Switch value={isDarkMode} onValueChange={toggleDarkMode} />
</View>
<View style={styles.settingItem}>
<Text style={styles.settingLabel}>通知</Text>
<Switch value={notifications} onValueChange={setNotifications} />
</View>
<View style={styles.settingItem}>
<Text style={styles.settingLabel}>自動同步</Text>
<Switch value={autoSync} onValueChange={setAutoSync} />
</View>
</View>
<TouchableOpacity style={styles.logoutButton} onPress={handleLogout}>
<Text style={styles.logoutButtonText}>登出</Text>
</TouchableOpacity>
<View style={styles.aboutSection}>
<Text style={styles.sectionTitle}>關於應用</Text>
<Text style={styles.aboutText}>版本: 1.0.0</Text>
<Text style={styles.aboutText}>開發者: Your Company Name</Text>
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
// ...
});
export default SettingsPage;
今天我們調整了bottom的頁面部分,並新增了user和調整setting頁面。明天接著繼續完成。