import { toast } from '@backpackapp-io/react-native-toast'; import Ionicons from '@expo/vector-icons/Ionicons'; import { Stack, useFocusEffect, useLocalSearchParams, useRouter } from 'expo-router'; import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Pressable, ScrollView, StyleSheet, TextInput, View } from 'react-native'; import Dropdown from 'react-native-input-select'; import { ThemedText } from '../../components/ThemedText'; import { ThemedView } from '../../components/ThemedView'; import { Category, CategoryQuery } from '../../models/category'; import { Task, TaskQuery } from '../../models/task'; import { CategoryRepository } from '../../repositories/CategoryRepository'; import { TaskRepository } from '../../repositories/TaskRepository'; import { SQLiteDataService } from '../../services/data/sqliteDataService'; const taskRepository = new TaskRepository(new SQLiteDataService(TaskQuery)); const categoryRepository = new CategoryRepository(new SQLiteDataService(CategoryQuery)); const timeUnits = [ { label: 'Minutes', value: 'minutes' }, { label: 'Hours', value: 'hours' }, { label: 'Days', value: 'days' }, { label: 'Weeks', value: 'weeks' }, { label: 'Months', value: 'months' } ]; const timeUnitToDays = (num: number, unit: string): number => { let result = 0; switch (unit) { // convert to days case 'minutes': result = num / 1440; // Convert minutes to days break; case 'hours': result = num / 24; // Convert hours to days break; case 'days': result = num; // Convert days to seconds break; case 'weeks': result = num * 7; // Convert weeks to days break; case 'months': result = num * 30; // Convert months to days (approximation) break; } return result; } export default function TasksForm() { const { t } = useTranslation(); const { task: taskJson } = useLocalSearchParams(); const task: Task = taskJson ? JSON.parse(taskJson as string) : null; const [categories, setCategories] = useState([]); const [selectedTimeUnit, setSelectedTimeUnit] = useState("days"); const router = useRouter(); const [newTask, setNewTask] = useState({ title: task?.title || '', daysToRedo: task?.daysToRedo || NaN, category: task?.category || -1, }); const adaptDaysToGoToUnit = () => { if (!task) return; if (task.daysToRedo! <= 1000 * 3600) { setSelectedTimeUnit("minutes"); setNewTask({ ...newTask, daysToRedo: task.daysToRedo! * 60 * 24 }); } else if (task.daysToRedo! <= 1000 * 3600 * 24) { setSelectedTimeUnit("hours"); setNewTask({ ...newTask, daysToRedo: task.daysToRedo! * 24 }); } else if (task.daysToRedo! <= 1000 * 3600 * 24 * 7) { setSelectedTimeUnit("days"); setNewTask({ ...newTask, daysToRedo: task.daysToRedo! }); } else if (task.daysToRedo! <= 1000 * 3600 * 24 * 30) { setSelectedTimeUnit("weeks"); setNewTask({ ...newTask, daysToRedo: task.daysToRedo! / 7 }); } else { setSelectedTimeUnit("months"); setNewTask({ ...newTask, daysToRedo: task.daysToRedo! / 30 }); } } useFocusEffect(React.useCallback(() => { categoryRepository.findAll().then((categories) => { categories.push(new Category("Create new category", "➕", 0)); setCategories(categories); if (newTask.category === 0) { setNewTask({ ...newTask, category: -1 }); } adaptDaysToGoToUnit(); }).catch((error) => { console.error("Error fetching categories:", error); }); }, [])); return ( null }} /> {t('app_name')} < Pressable onPress={() => { router.back(); } }> < ScrollView style={styles.scrollView} > {t('add_new_task')} setNewTask({ ...newTask, title: e.nativeEvent.text })} /> unit.value === selectedTimeUnit)?.label} ${t('after_which_task_is_due')}`} style={styles.inputText} placeholderTextColor="#333" keyboardType='numeric' value={isNaN(newTask.daysToRedo ?? NaN) ? undefined : newTask.daysToRedo?.toString()} onChange={(e) => setNewTask({ ...newTask, daysToRedo: e.nativeEvent.text.length > 0 ? parseInt(e.nativeEvent.text) : NaN })} /> setSelectedTimeUnit(value?.toString() ?? "")} selectedValue={selectedTimeUnit} maxSelectableItems={1} checkboxControls={{ checkboxLabelStyle: { fontSize: 20, paddingVertical: 10 }, checkboxStyle: { backgroundColor: '#e744a9ff', borderColor: 'transparent', } }} dropdownIconStyle={{ alignSelf: 'flex-start', margin: 0, padding: 0, marginTop: -30 }} dropdownContainerStyle={ { flex: 1, marginTop: -2 } } dropdownStyle={{ borderColor: '#ccc', borderWidth: 2, backgroundColor: '#fff', }} /> ({ label: `${category.icon} ${category.title}`, value: category.id })) } onValueChange={(value) => { if (value === 0) { router.push({ pathname: "./categoryForm" }); } setNewTask({ ...newTask, category: (value ?? -1) as number } ) }} selectedValue={newTask.category > -1 ? newTask.category : undefined} maxSelectableItems={1} checkboxControls={{ checkboxLabelStyle: { fontSize: 20, paddingVertical: 10 }, checkboxStyle: { backgroundColor: '#e744a9ff', borderColor: 'transparent', } }} dropdownIconStyle={{ alignSelf: 'flex-start', margin: 0, padding: 0, marginTop: -30 }} dropdownStyle={{ borderColor: '#ccc', borderWidth: 2 }} /> { newTask.daysToRedo = timeUnitToDays(newTask.daysToRedo, selectedTimeUnit); if (newTask.title.length > 0 && newTask.daysToRedo > 0 && newTask.category > -1) { if (task && task.id) { // Update existing task taskRepository.update(task.id, { ...task, ...newTask }).then(() => { toast.success("Task updated successfully!"); router.back(); }); } else { // Create new task taskRepository.create(new Task(newTask.title, newTask.daysToRedo, newTask.category)).then(() => { toast.success("Task added successfully!"); router.back(); }); } } else { toast.error("Please fill in all fields correctly."); } }}> {task?.id ? t('update_task') : t('add_task')} < View style={{ height: 50 }} /> ); } const styles = StyleSheet.create({ mainContainer: { flex: 1, }, headerContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 8, paddingHorizontal: 24, paddingTop: 50, paddingBottom: 18, backgroundColor: '#6a254fff', }, scrollView: { padding: 24, flex: 1, }, stepContainer: { gap: 24, marginBottom: 8, marginTop: 16, }, reactLogo: { height: 178, width: 290, bottom: 0, left: 0, position: 'absolute', }, inputText: { flex: 1, backgroundColor: '#fff', height: 60, color: '#333333', borderRadius: 8, padding: 10, lineHeight: 30, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 32, borderWidth: 2, borderColor: '#ccc', }, textArea: { backgroundColor: '#fff', color: '#333333', borderRadius: 8, padding: 10, paddingHorizontal: 32, minHeight: 100, textAlignVertical: 'top' }, addButton: { flexDirection: 'row', gap: 8, backgroundColor: '#b91f7eff', color: '#fff', borderRadius: 8, padding: 20, alignItems: 'center', justifyContent: 'center', }, addButtonText: { color: '#fff', fontSize: 16, fontWeight: 'bold', }, });