fixxed color selector in the category settings and fixxed drag and drop
Build APK / build (push) Canceled after 2m0s
Build APK / build (push) Canceled after 2m0s
subtask
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useMemo, useRef, useState, useCallback, useEffect } from 'react';
|
||||
import { View, Text, StyleSheet, SafeAreaView, ScrollView, TouchableOpacity, Animated, Dimensions } from 'react-native';
|
||||
import { useRouter } from 'expo-router';
|
||||
import { View, Text, StyleSheet, SafeAreaView, ScrollView, TouchableOpacity, Animated, Dimensions, BackHandler, KeyboardAvoidingView } from 'react-native';
|
||||
import { useRouter, useFocusEffect } from 'expo-router';
|
||||
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
||||
import { Header } from '@/components/Header';
|
||||
import { useTasksByDate, useTasksInMonth } from '@/hooks/useTasks';
|
||||
@@ -15,10 +15,10 @@ import Task from '@/models/Task';
|
||||
import { format, addMonths, addDays, startOfMonth, isSameDay, isSameMonth, isToday } from 'date-fns';
|
||||
import { Q } from '@nozbe/watermelondb';
|
||||
import Svg, { Path, Circle } from 'react-native-svg';
|
||||
import { desaturate } from '@/theme';
|
||||
import type { ThemeColors } from '@/theme';
|
||||
|
||||
const WIDTH = Dimensions.get('window').width;
|
||||
const ORANGE = '#FF7043';
|
||||
const GERMAN_WEEKDAYS = ['mo', 'di', 'mi', 'do', 'fr', 'sa', 'so'];
|
||||
const MONTH_NAMES = [
|
||||
'January', 'February', 'March', 'April', 'May', 'June',
|
||||
@@ -43,6 +43,13 @@ export default function CalendarScreen() {
|
||||
const selectedDateRef = useRef(selectedDate);
|
||||
selectedDateRef.current = selectedDate;
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
const sub = BackHandler.addEventListener('hardwareBackPress', () => true);
|
||||
return () => sub.remove();
|
||||
}, [])
|
||||
);
|
||||
|
||||
const translateX = useRef(new Animated.Value(0)).current;
|
||||
const animatingRef = useRef(false);
|
||||
const gridWidthRef = useRef<number>(WIDTH);
|
||||
@@ -181,17 +188,17 @@ export default function CalendarScreen() {
|
||||
|
||||
return (
|
||||
<SafeAreaView style={[styles.container, { backgroundColor: theme.background }]}>
|
||||
<GestureDetector gesture={pan}>
|
||||
<View style={styles.flex}>
|
||||
<Header title="Calendar" showLogo={false} />
|
||||
<Header title="Calendar" showLogo={false} />
|
||||
|
||||
<ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={styles.scrollContent}>
|
||||
<Animated.View
|
||||
onLayout={(e) => {
|
||||
gridWidthRef.current = e.nativeEvent.layout.width;
|
||||
}}
|
||||
style={[styles.calendarArea, { transform: [{ translateX }] }]}
|
||||
>
|
||||
<KeyboardAvoidingView style={styles.kbAvoid} behavior="padding">
|
||||
<ScrollView style={styles.scrollBody} showsVerticalScrollIndicator={false} contentContainerStyle={styles.scrollContent}>
|
||||
<GestureDetector gesture={pan}>
|
||||
<Animated.View
|
||||
onLayout={(e) => {
|
||||
gridWidthRef.current = e.nativeEvent.layout.width;
|
||||
}}
|
||||
style={[styles.calendarArea, { transform: [{ translateX }] }]}
|
||||
>
|
||||
<View style={styles.monthRow}>
|
||||
<TouchableOpacity
|
||||
onPress={() => transitionTo(-1)}
|
||||
@@ -199,7 +206,7 @@ export default function CalendarScreen() {
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<Svg width={20} height={20} viewBox="0 0 24 24">
|
||||
<Path d="M15 18l-6-6 6-6" stroke={theme.textFaint} strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
<Path d="M15 18l-6-6 6-6" stroke={theme.textSecondary} strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
</Svg>
|
||||
</TouchableOpacity>
|
||||
|
||||
@@ -207,7 +214,7 @@ export default function CalendarScreen() {
|
||||
<TouchableOpacity onPress={() => setMonthPickerVisible(true)} activeOpacity={0.7} style={styles.monthButton}>
|
||||
<Text style={[styles.monthLabel, { color: theme.text }]}>{format(visibleMonth, 'MMMM')}</Text>
|
||||
<Svg width={14} height={14} viewBox="0 0 24 24">
|
||||
<Path d="M6 9l6 6 6-6" stroke={theme.textMuted} strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
<Path d="M6 9l6 6 6-6" stroke={theme.textSecondary} strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
</Svg>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => setYearPickerVisible(true)} activeOpacity={0.7} style={styles.yearButton}>
|
||||
@@ -221,7 +228,7 @@ export default function CalendarScreen() {
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<Svg width={20} height={20} viewBox="0 0 24 24">
|
||||
<Path d="M9 6l6 6-6 6" stroke={theme.textFaint} strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
<Path d="M9 6l6 6-6 6" stroke={theme.textSecondary} strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
</Svg>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
@@ -252,8 +259,9 @@ export default function CalendarScreen() {
|
||||
</View>
|
||||
))}
|
||||
</Animated.View>
|
||||
</GestureDetector>
|
||||
|
||||
<View style={styles.panelHeader}>
|
||||
<View style={styles.panelHeader}>
|
||||
<Text style={[styles.panelDate, { color: theme.text }]}>{format(selectedDate, 'EEEE, MMMM d')}</Text>
|
||||
{selectedDayTasks.length > 0 && (
|
||||
<Text style={[styles.panelCount, { color: theme.textFaint }]}>
|
||||
@@ -276,14 +284,14 @@ export default function CalendarScreen() {
|
||||
onPress={() => handleToggleComplete(task.id)}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<Svg width={22} height={22} viewBox="0 0 24 24">
|
||||
<Svg width={30} height={30} viewBox="0 0 24 24">
|
||||
{task.completed ? (
|
||||
<>
|
||||
<Circle cx={12} cy={12} r={10} fill={theme.accent} />
|
||||
<Path d="M7 12l3 3 7-7" stroke="#FFFFFF" strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
</>
|
||||
) : (
|
||||
<Circle cx={12} cy={12} r={10} stroke={theme.textMuted} strokeWidth={2} fill="none" />
|
||||
<Circle cx={12} cy={12} r={10} stroke={theme.textSecondary} strokeWidth={2.5} fill="none" />
|
||||
)}
|
||||
</Svg>
|
||||
</TouchableOpacity>
|
||||
@@ -303,9 +311,7 @@ export default function CalendarScreen() {
|
||||
|
||||
<TouchableOpacity style={styles.menuButton} onPress={() => openTaskEdit(task.id)} activeOpacity={0.7} accessibilityRole="button" accessibilityLabel={`Edit ${task.title}`}>
|
||||
<Svg width={20} height={20} viewBox="0 0 24 24">
|
||||
<Circle cx={12} cy={5} r={1.5} fill={theme.textMuted} />
|
||||
<Circle cx={12} cy={12} r={1.5} fill={theme.textMuted} />
|
||||
<Circle cx={12} cy={19} r={1.5} fill={theme.textMuted} />
|
||||
<Path d="M9 6l6 6-6 6" stroke={theme.textSecondary} strokeWidth={2.5} strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
</Svg>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
@@ -337,28 +343,27 @@ export default function CalendarScreen() {
|
||||
)}
|
||||
</ScrollView>
|
||||
|
||||
<QuickAddBar dueDate={selectedDate.getTime()} placeholder={`Add event for ${format(selectedDate, 'MMM d')}`} />
|
||||
<QuickAddBar dueDate={selectedDate.getTime()} placeholder={`Add event for ${format(selectedDate, 'MMM d')}`} />
|
||||
</KeyboardAvoidingView>
|
||||
|
||||
{modals(() => {})}
|
||||
{modals(() => {})}
|
||||
|
||||
<OptionPickerModal
|
||||
visible={monthPickerVisible}
|
||||
title="Select Month"
|
||||
options={monthOptions}
|
||||
selectedValue={String(visibleMonth.getMonth())}
|
||||
onSelect={handleSelectMonth}
|
||||
onClose={() => setMonthPickerVisible(false)}
|
||||
/>
|
||||
<OptionPickerModal
|
||||
visible={yearPickerVisible}
|
||||
title="Select Year"
|
||||
options={yearOptions}
|
||||
selectedValue={String(visibleMonth.getFullYear())}
|
||||
onSelect={handleSelectYear}
|
||||
onClose={() => setYearPickerVisible(false)}
|
||||
/>
|
||||
</View>
|
||||
</GestureDetector>
|
||||
<OptionPickerModal
|
||||
visible={monthPickerVisible}
|
||||
title="Select Month"
|
||||
options={monthOptions}
|
||||
selectedValue={String(visibleMonth.getMonth())}
|
||||
onSelect={handleSelectMonth}
|
||||
onClose={() => setMonthPickerVisible(false)}
|
||||
/>
|
||||
<OptionPickerModal
|
||||
visible={yearPickerVisible}
|
||||
title="Select Year"
|
||||
options={yearOptions}
|
||||
selectedValue={String(visibleMonth.getFullYear())}
|
||||
onSelect={handleSelectYear}
|
||||
onClose={() => setYearPickerVisible(false)}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
@@ -376,7 +381,7 @@ function cellTitle(tasks: Task[]): string | null {
|
||||
function cellColor(tasks: Task[], categories: { id: string; color: string }[]): string {
|
||||
if (tasks.length === 0) return '#8E8E8E';
|
||||
const cat = categories.find((c) => c.id === tasks[0].categoryId);
|
||||
return cat?.color ?? '#8E8E8E';
|
||||
return cat ? desaturate(cat.color, 0.3) : '#8E8E8E';
|
||||
}
|
||||
|
||||
interface DayCellProps {
|
||||
@@ -393,7 +398,7 @@ interface DayCellProps {
|
||||
const DayCell = React.memo(function DayCell({ day, label, dotColor, selected, today, inMonth, theme, onPress }: DayCellProps) {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.dayCell, selected && { backgroundColor: ORANGE }]}
|
||||
style={[styles.dayCell, selected && { backgroundColor: theme.accentSoft, borderColor: theme.accentBorder }]}
|
||||
onPress={() => onPress(day)}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
@@ -401,8 +406,8 @@ const DayCell = React.memo(function DayCell({ day, label, dotColor, selected, to
|
||||
style={[
|
||||
styles.dayNumber,
|
||||
{ color: theme.text },
|
||||
!inMonth && { color: theme.borderStrong },
|
||||
today && !selected && { color: ORANGE },
|
||||
!inMonth && { color: theme.textMuted },
|
||||
today && !selected && { color: theme.accent },
|
||||
selected && styles.dayNumberSelected,
|
||||
]}
|
||||
>
|
||||
@@ -425,12 +430,15 @@ const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
flex: {
|
||||
scrollContent: {
|
||||
paddingBottom: 16,
|
||||
flexGrow: 1,
|
||||
},
|
||||
scrollBody: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollContent: {
|
||||
paddingBottom: 96,
|
||||
flexGrow: 1,
|
||||
kbAvoid: {
|
||||
flex: 1,
|
||||
},
|
||||
calendarArea: {
|
||||
paddingHorizontal: 12,
|
||||
@@ -565,8 +573,8 @@ const styles = StyleSheet.create({
|
||||
alignItems: 'center',
|
||||
},
|
||||
checkCircle: {
|
||||
width: 24,
|
||||
marginRight: 10,
|
||||
width: 30,
|
||||
marginRight: 12,
|
||||
},
|
||||
eventTitleTouch: {
|
||||
flex: 1,
|
||||
|
||||
Reference in New Issue
Block a user