import { defaultStyles } from '@/constants/defaultStyles'; import { SUBJECT_COLOR_KEYS, SUBJECT_COLORS, type SubjectColor } from '@/lib/subjectColors'; import { supabase } from '@/lib/supabase'; import type { Subject } from '@/lib/types'; import { router, Stack, useLocalSearchParams } from 'expo-router'; import { useEffect, useMemo, useState } from 'react'; import { ActivityIndicator, Alert, Keyboard, KeyboardAvoidingView, Platform, Pressable, ScrollView, Text, TextInput, TouchableWithoutFeedback, View } from 'react-native'; export default function UpsertSubject() { const { sId } = useLocalSearchParams<{ sId?: string }>(); const isEditMode = Boolean(sId); const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const [isActive, setIsActive] = useState(true); const [color, setColor] = useState('blue'); const [isLoading, setIsLoading] = useState(isEditMode); const [isSaving, setIsSaving] = useState(false); useEffect(() => { if (!isEditMode || !sId) return; const loadSubject = async () => { setIsLoading(true); const { data, error } = await supabase .from('subjects') .select('*') .eq('sId', sId) .single(); setIsLoading(false); if (error || !data ) { Alert.alert('Subject could not be loaded, please try again'); router.back(); return; } const subject = data as Subject; setTitle(subject.title ?? ''); setDescription(subject.description ?? ''); setIsActive(subject.isActive ?? true); setColor(subject.color ?? 'blue'); }; loadSubject(); }, [isEditMode, sId]); 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; } setIsSaving(true); const payload = { title: title.trim(), description : description.trim(), isActive, color, lastChanged: new Date().toISOString(), uId: data.user.id, }; const result = isEditMode && sId ? await supabase.from('subjects').update(payload).eq('sId', sId) : await supabase.from('subjects').insert(payload); setIsSaving(false); if(result.error) { Alert.alert( isEditMode ? 'Subject could not be updated, please try again' : 'Subject could not be created, please try again' ); return; } Alert.alert( isEditMode ? 'Subject updated successfully!' : 'Subject created successfully!' ); 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'; const selectedColor = useMemo(() => SUBJECT_COLORS[color], [color]); if (isLoading) { return ( ); } return ( <> {isEditMode ? 'Edit Subject' : 'Create Subject'} {isEditMode? ' Update this subject and keep your study structure organized.' : 'Add a subject to organize your assignments and studyt tasks.'} Title Description Color Preview {title.trim().charAt(0).toUpperCase() || 'S'} {title.trim() || 'Subject Preview'} {description.trim() || 'This color will be used as the subject card accent.'} {isActive ? 'Active' : 'Inactive'} {SUBJECT_COLOR_KEYS.map((colorKey) => { const colorOption = SUBJECT_COLORS[colorKey]; const isSelected = color === colorKey; return ( setColor(colorKey)} className="mr-3 mb-3 rounded-2xl border border-app-border bg-app--surface p-2" style={{ borderColor: isSelected ? colorOption.strong : '#FFFFFF', }} > {colorOption.label} ); })} setIsActive((state) => !state)} disabled={isSaving} className={`mb-6 flex-row items-center rounded-2xl border p-4 ${ isActive ? 'border-accent bg-accent-soft' : 'border-app-border bg-app-subtle' }`} > {isActive && ( )} Active subject Active subjects appear in your main study workflow. {isSaving ? ( {isEditMode ? 'Saving...' : 'Creating...'} ) : ( {isEditMode ? 'Save Changes' : 'Create Subject'} )} router.back()} disabled={isSaving} > Cancel ); }