import { defaultStyles } from '@/constants/defaultStyles'; import { CheckAssignmentCompletion } from '@/lib/progress'; import { supabase } from '@/lib/supabase'; import type { Task } from '@/lib/types'; import { router, Stack, useLocalSearchParams } from 'expo-router'; import { useEffect, useState } from 'react'; import { ActivityIndicator, Alert, Keyboard, KeyboardAvoidingView, Platform, Pressable, ScrollView, Text, TextInput, TouchableWithoutFeedback, View, } from 'react-native'; export default function UpsertTask() { const { tId, aId: routeAId, flow } = useLocalSearchParams<{ tId?: string; aId?: string; flow?: string; }>(); const isEditMode = Boolean(tId); const isSetupFlow = flow === 'setup'; const [title, SetTitle] = useState(''); const [description, SetDescription] = useState(''); const [isCompleted, SetIsCompleted] = useState(false); const [assignmentId, SetAssignmentId] = useState(routeAId ?? null); const [isLoading, SetIsLoading] = useState(isEditMode); const [isSaving, SetIsSaving] = useState(false); useEffect(() => { if (!isEditMode || !tId) { SetIsLoading(false); return; } const loadTask = async () => { SetIsLoading(true); const { data, error } = await supabase .from('tasks') .select('*') .eq('tId', tId) .single(); SetIsLoading(false); if (error || !data) { Alert.alert('Task could not be loaded, please try again'); router.back(); return; } const task = data as Task; SetTitle(task.title ?? ''); SetDescription(task.description ?? ''); SetIsCompleted(task.isCompleted ?? false); SetAssignmentId(task.aId ?? routeAId ?? null); }; loadTask(); }, [isEditMode, tId, routeAId]); const handleSubmit = async () => { if (title.trim() === '') { Alert.alert('Title is required!'); return; } const { data, error: userError } = await supabase.auth.getUser(); if (userError || !data.user) { router.replace('/login'); return; } if (!assignmentId) { Alert.alert('Missing assignment', 'This task is not linked to an assignment.'); return; } SetIsSaving(true); const payload = { title: title.trim(), description: description.trim(), isCompleted, lastChanged: new Date().toISOString(), uId: data.user.id, aId: assignmentId, }; const result = isEditMode && tId ? await supabase.from('tasks').update(payload).eq('tId', tId) : await supabase.from('tasks').insert(payload).select().single(); if (result.error) { SetIsSaving(false); Alert.alert( isEditMode ? 'Task could not be updated, please try again' : 'Task could not be created, please try again' ); return; } try { await CheckAssignmentCompletion(assignmentId); } catch { SetIsSaving(false); Alert.alert('Failed to update assignment completion state'); return; } SetIsSaving(false); if (!isEditMode && isSetupFlow && result.data?.tId) { router.replace({ pathname: '/task/timer', params: { tId: result.data.tId }, }); return; } Alert.alert( isEditMode ? 'Task successfully updated!' : 'Task successfully created!' ); router.back(); }; const inputClassName = 'rounded-2xl border border-app-border bg-app-subtle px-4 py-3 text-base text-text-main'; const labelClassName = 'mb-2 text-sm font-semibold text-text-secondary'; if (isLoading) { return ( ); } return ( <> {isEditMode ? 'Edit Task' : 'Create Task'} {isEditMode ? 'Update this task and keep your assignment moving forward.' : 'Add a small step to move this assignment forward.'} Title Description SetIsCompleted((state) => !state)} disabled={isSaving} className={`mb-6 flex-row items-center rounded-2xl border p-4 ${ isCompleted ? 'border-accent bg-accent-soft' : 'border-app-border bg-app-subtle' }`} > {isCompleted && ( )} Mark as completed You can change this later. {isSaving ? ( {isEditMode ? 'Saving...' : 'Creating...'} ) : ( {isEditMode ? 'Save Changes' : 'Create Task'} )} router.back()} disabled={isSaving} > Cancel ); }