106 lines
3.4 KiB
TypeScript
106 lines
3.4 KiB
TypeScript
import React, { useCallback, useMemo, useState } from 'react';
|
|
import { View, Text, StyleSheet, SafeAreaView, BackHandler, KeyboardAvoidingView, TouchableOpacity } from 'react-native';
|
|
import { useFocusEffect } from 'expo-router';
|
|
import { Header } from '@/components/Header';
|
|
import { CategoryFilter } from '@/components/CategoryFilter';
|
|
import { TaskList } from '@/components/TaskList';
|
|
import { QuickAddBar } from '@/components/QuickAddBar';
|
|
import { useDatabase } from '@/hooks/useDatabase';
|
|
import { useSettings } from '@/theme';
|
|
import Svg, { Path, Circle } from 'react-native-svg';
|
|
|
|
export default function TasksScreen() {
|
|
const { isReady } = useDatabase();
|
|
const { theme, showCompleted, setShowCompleted } = useSettings();
|
|
const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
|
|
|
|
const categoryIds = useMemo(() => selectedCategories, [selectedCategories]);
|
|
|
|
useFocusEffect(
|
|
useCallback(() => {
|
|
const sub = BackHandler.addEventListener('hardwareBackPress', () => true);
|
|
return () => sub.remove();
|
|
}, [])
|
|
);
|
|
|
|
if (!isReady) {
|
|
return (
|
|
<View style={[styles.container, { backgroundColor: theme.background }]}>
|
|
<Text style={{ color: theme.textFaint }}>Loading...</Text>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
|
|
<Header title="ToDo" showLogo={false} />
|
|
<View style={styles.categoryFilterWrapper}>
|
|
<CategoryFilter selected={selectedCategories} onSelect={setSelectedCategories} />
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.completedToggle,
|
|
{ backgroundColor: theme.card, borderColor: showCompleted ? theme.accent : theme.borderStrong },
|
|
]}
|
|
onPress={() => setShowCompleted(!showCompleted)}
|
|
activeOpacity={0.8}
|
|
accessibilityRole="switch"
|
|
accessibilityLabel="Show completed tasks"
|
|
accessibilityState={{ checked: showCompleted }}
|
|
>
|
|
<Svg width={14} height={14} viewBox="0 0 24 24">
|
|
<Circle
|
|
cx={12}
|
|
cy={12}
|
|
r={9}
|
|
stroke={showCompleted ? theme.accent : theme.textMuted}
|
|
strokeWidth={2}
|
|
fill="none"
|
|
/>
|
|
{showCompleted && (
|
|
<Path d="M7 12.5l3.5 3.5 6.5-7" stroke={theme.accent} strokeWidth={2.2} strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
|
)}
|
|
</Svg>
|
|
<Text style={[styles.completedToggleText, { color: showCompleted ? theme.text : theme.textMuted }]}>
|
|
Completed
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
<KeyboardAvoidingView
|
|
style={styles.kbAvoid}
|
|
behavior="padding"
|
|
>
|
|
<TaskList categoryIds={categoryIds} showCompleted={showCompleted} />
|
|
<QuickAddBar />
|
|
</KeyboardAvoidingView>
|
|
</SafeAreaView>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
},
|
|
categoryFilterWrapper: {
|
|
justifyContent: 'center',
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
paddingRight: 12,
|
|
},
|
|
completedToggle: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: 5,
|
|
paddingHorizontal: 10,
|
|
paddingVertical: 8,
|
|
borderRadius: 18,
|
|
borderWidth: 1.5,
|
|
alignSelf: 'center',
|
|
},
|
|
completedToggleText: {
|
|
fontSize: 12,
|
|
fontWeight: '600',
|
|
},
|
|
kbAvoid: {
|
|
flex: 1,
|
|
},
|
|
}); |