import { formatDate, formatDateTime } from '@/lib/date'; import { CheckSubjectCompletion } from '@/lib/progress'; import { SUBJECT_COLORS, type SubjectColor } from '@/lib/subjectColors'; import { supabase } from '@/lib/supabase'; import type { Assignment } from '@/lib/types'; import { Session } from '@supabase/supabase-js'; import { router, Stack, useFocusEffect, useLocalSearchParams } from 'expo-router'; import { useCallback, useEffect, useState } from 'react'; import { Alert, Pressable, SectionList, Text, View } from 'react-native'; export type Subject = { sId: string; title: string; description: string; isActive: boolean; lastChanged: string; uId: string; color: SubjectColor; }; export default function ViewDetailsSubject() { const { sId } = useLocalSearchParams<{ sId: string }>(); const [subject, SetSubject] = useState(null); const [assignments, SetAssignments] = useState([]); const [session, SetSession] = useState(null); const assignmentSections = [ { title: 'Active Assignments', data: assignments.filter((assignment) => !assignment.isCompleted), emptyMessage: 'No active assignments', }, { title: 'Completed Assignments', data: assignments.filter((assignment) => assignment.isCompleted), emptyMessage: 'No completed assignments', }, ]; useEffect(() => { supabase.auth.getSession().then(({ data }) => SetSession(data.session ?? null)); const { data: sub } = supabase.auth.onAuthStateChange((_event, newSession) => { SetSession(newSession); }); return () => sub.subscription.unsubscribe(); }, []); const GetSubject = async (subjectId: string) => { const { data, error } = await supabase .from('subjects') .select('*') .eq('sId', subjectId) .single(); if (error) { Alert.alert('Subject could not be fetched, please try again'); return; } SetSubject((data as Subject) ?? null); }; const GetAssignments = async (subjectId: string) => { const { data, error } = await supabase .from('assignments') .select('*') .eq('sId', subjectId) .order('deadline', { ascending: true }); if (error) { Alert.alert('Assignments could not be fetched, please try again'); return; } SetAssignments(data ?? []); }; useFocusEffect( useCallback(() => { if (session && sId) { GetSubject(sId); GetAssignments(sId); } }, [session, sId]) ); const DeleteSubject = async (subjectId: string) => { Alert.alert( 'Delete Subject', 'Are you sure you want to delete this subject?', [ { text: 'Cancel', style: 'cancel', }, { text: 'Delete', style: 'destructive', onPress: async () => { const { error } = await supabase .from('subjects') .delete() .eq('sId', subjectId); if (error) { Alert.alert('Subject could not be deleted, please try again'); return; } Alert.alert('Subject deleted successfully!'); router.back(); }, }, ] ); }; const DeleteAssignment = async (assignmentId: string, subjectId: string) => { Alert.alert( 'Delete Assignment', 'Are you sure you want to delete this assignment?', [ { text: 'Cancel', style: 'cancel', }, { text: 'Delete', style: 'destructive', onPress: async () => { const { error } = await supabase .from('assignments') .delete() .eq('aId', assignmentId); if (error) { Alert.alert('Assignment could not be deleted, please try again'); return; } if (subjectId) { try { await CheckSubjectCompletion(subjectId); } catch { Alert.alert('Failed to update subject status'); } } await GetAssignments(subjectId); await GetSubject(subjectId); Alert.alert('Assignment deleted successfully!'); }, }, ] ); }; const completedAssignments = assignments.filter((assignment) => assignment.isCompleted).length; const totalAssignments = assignments.length; const remainingAssignments = totalAssignments - completedAssignments; const progress = assignments.length === 0 ? 0 : Math.round((completedAssignments / totalAssignments) * 100); if (!subject) { return ( Subject not found The subject could not be loaded. router.back()} > Go back ); } const colorKey: SubjectColor = subject.color ?? 'slate'; const colorSet = SUBJECT_COLORS[colorKey]; const firstLetter = subject.title?.trim().charAt(0).toUpperCase() || 'S'; return ( ( await supabase.auth.signOut()} > Logout ), }} /> item.aId} showsVerticalScrollIndicator={false} stickySectionHeadersEnabled={false} ListHeaderComponent={ {firstLetter} {subject.title} {subject.description ? ( {subject.description} ) : ( No description added. )} {subject.isActive ? 'Active' : 'Inactive'} Assignments completed {completedAssignments}/{totalAssignments} {remainingAssignments === 0 ? 'All assignments complete' : `${remainingAssignments} assignment${ remainingAssignments === 1 ? '' : 's' } remaining`} Based only on completed assignments in this subject. Last changed: {formatDateTime(subject.lastChanged)} router.push({ pathname: '/subject/upsertSubject', params: { sId: subject.sId }, }) } > Edit DeleteSubject(subject.sId)} > Delete router.push({ pathname: '/assignment/upsertAssignment', params: { sId: subject.sId }, }) } > Create Assignment } renderSectionHeader={({ section: { title, data } }) => ( {title} {data.length} )} renderItem={({ item }) => { const isOwner = session?.user.id === item.uId; return ( router.push({ pathname: '/assignment/viewDetailsAssignment', params: { aId: item.aId }, }) } > {item.title} {item.description ? ( {item.description} ) : null} Deadline: {formatDate(item.deadline)} {isOwner && ( router.push({ pathname: '/assignment/upsertAssignment', params: { aId: item.aId }, }) } > Edit DeleteAssignment(item.aId, item.sId)} > Delete )} ); }} renderSectionFooter={({ section }) => section.data.length === 0 ? ( {section.emptyMessage} {assignments.length === 0 ? 'Create the first assignment to give this subject a real study path.' : 'Assignments for this subject will show up here.'} ) : ( ) } /> ); }