diff --git a/app/(tabs)/assignments.tsx b/app/(tabs)/assignments.tsx index 69190ab..8fb9f77 100644 --- a/app/(tabs)/assignments.tsx +++ b/app/(tabs)/assignments.tsx @@ -1,4 +1,5 @@ import { defaultStyles } from '@/constants/defaultStyles'; +import { CheckSubjectCompletion } from '@/lib/progress'; import { supabase } from '@/lib/supabase'; import type { Assignment, Task } from '@/lib/types'; import { Ionicons } from '@expo/vector-icons'; @@ -97,7 +98,7 @@ export default function Assignments() { }, [session]) ); - const DeleteAssignment = async (aId: string) => { + const DeleteAssignment = async (aId: string, sId: string) => { Alert.alert( 'Delete Assignment', 'Are you sure you want to delete this assignment?', @@ -121,6 +122,13 @@ export default function Assignments() { } Alert.alert('Assignment deleted successfully!'); + + try { + await CheckSubjectCompletion(sId); + } catch { + Alert.alert("Failed to update subject status"); + } + GetAssignments(); }, }, @@ -296,7 +304,7 @@ export default function Assignments() { DeleteAssignment(item.aId)} + onPress={() => DeleteAssignment(item.aId, item.sId)} > Delete diff --git a/app/(tabs)/subjects.tsx b/app/(tabs)/subjects.tsx index 323d021..f5f5f79 100644 --- a/app/(tabs)/subjects.tsx +++ b/app/(tabs)/subjects.tsx @@ -1,6 +1,6 @@ import { defaultStyles } from '@/constants/defaultStyles'; import { supabase } from '@/lib/supabase'; -import type { Subject } from '@/lib/types'; +import type { Assignment, Subject } from '@/lib/types'; import { Ionicons } from '@expo/vector-icons'; import { Session } from '@supabase/supabase-js'; import { router, Stack, useFocusEffect } from 'expo-router'; @@ -15,6 +15,7 @@ import { export default function Subjects() { const [subjects, SetSubjects] = useState([]); + const [assignmentsBySubject, SetAssignmentsBySubject] = useState>({}); const [session, SetSession] = useState(null); const subjectSections = [ @@ -45,17 +46,47 @@ export default function Subjects() { }, []); const GetSubjects = async () => { - const { data, error } = await supabase + const { data: subjectsData, error: subjectsError } = await supabase .from('subjects') .select('*') .order('lastChanged', { ascending: false }); - if (error) { + if (subjectsError) { Alert.alert('Subjects could not be fetched, please try again'); return; } - SetSubjects(data ?? []); + const subjectRows = subjectsData ?? []; + SetSubjects(subjectsData ?? []); + + if (subjectRows.length === 0) { + SetAssignmentsBySubject({}); + return; + } + + const sIds = subjectRows.map((subject) => subject.sId); + + const { data: assignmentsData, error: assignmentsError } = await supabase + .from('assignments') + .select('*') + .in('sId', sIds); + + if (assignmentsError) { + Alert.alert('Subject assignments could not be fetched, please try again'); + SetAssignmentsBySubject({}); + return; + } + + const groupedAssignments: Record = {}; + + for (const assignment of assignmentsData ?? []) { + if (!groupedAssignments[assignment.sId]) { + groupedAssignments[assignment.sId] = []; + } + groupedAssignments[assignment.sId].push(assignment); + } + + SetAssignmentsBySubject(groupedAssignments); }; useFocusEffect( @@ -169,6 +200,9 @@ export default function Subjects() { renderItem={({ item }) => { const isOwner = session?.user.id === item.uId; + const subjectAssignments = assignmentsBySubject[item.sId] ?? []; + const progress = subjectAssignments.length === 0 ? 0 : Math.round((subjectAssignments.filter(assignment => assignment.isCompleted).length / subjectAssignments.length) * 100); + return ( + + {progress}% + + + + + diff --git a/app/(tabs)/tasks.tsx b/app/(tabs)/tasks.tsx index 6b204e4..7e08755 100644 --- a/app/(tabs)/tasks.tsx +++ b/app/(tabs)/tasks.tsx @@ -1,4 +1,5 @@ import { defaultStyles } from '@/constants/defaultStyles'; +import { CheckAssignmentCompletion } from '@/lib/progress'; import { supabase } from '@/lib/supabase'; import type { Task } from '@/lib/types'; import { Ionicons } from '@expo/vector-icons'; @@ -63,7 +64,7 @@ export default function Tasks() { }, [session]) ); - const DeleteTask = async (tId: string) => { + const DeleteTask = async (tId: string, aId: string) => { Alert.alert( 'Delete Task', 'Are you sure you want to delete this task?', @@ -87,6 +88,13 @@ export default function Tasks() { } Alert.alert('Task deleted successfully!'); + + try { + await CheckAssignmentCompletion(aId); + } catch { + Alert.alert("Failed to update assignment completion state"); + } + GetTasks(); }, }, @@ -237,7 +245,7 @@ export default function Tasks() { DeleteTask(item.tId)} + onPress={() => DeleteTask(item.tId, item.aId)} > Delete diff --git a/app/assignment/createAssignment.tsx b/app/assignment/createAssignment.tsx index 68be4c6..f377cb0 100644 --- a/app/assignment/createAssignment.tsx +++ b/app/assignment/createAssignment.tsx @@ -1,5 +1,6 @@ import { defaultStyles } from '@/constants/defaultStyles'; import * as AsyncStorage from '@/lib/asyncStorage'; +import { CheckSubjectCompletion } from '@/lib/progress'; import { supabase } from '@/lib/supabase'; import * as Notifications from 'expo-notifications'; import { router, Stack, useLocalSearchParams } from 'expo-router'; @@ -93,6 +94,14 @@ export default function CreateAssignment() { } } + if (sId) { + try { + await CheckSubjectCompletion(sId); + } catch { + Alert.alert("Failed to update subject status"); + } + } + SetTitle(''); SetDescription(''); SetDeadline(''); diff --git a/app/assignment/editAssignment.tsx b/app/assignment/editAssignment.tsx index 76e0348..7115942 100644 --- a/app/assignment/editAssignment.tsx +++ b/app/assignment/editAssignment.tsx @@ -1,5 +1,6 @@ import { defaultStyles } from '@/constants/defaultStyles'; import { GetAssignmentNotificationId, RemoveAssignmentNotificationId, SaveAssignmentNotificationId } from '@/lib/asyncStorage'; +import { CheckSubjectCompletion } from '@/lib/progress'; import { supabase } from '@/lib/supabase'; import type { Assignment } from '@/lib/types'; import * as Notifications from 'expo-notifications'; @@ -115,6 +116,14 @@ export default function EditAssignment() { } } + if (assignmentData.sId) { + try { + await CheckSubjectCompletion(assignmentData.sId); + } catch { + Alert.alert("Failed to update subject status"); + } + } + router.back(); } diff --git a/app/assignment/viewDetailsAssignment.tsx b/app/assignment/viewDetailsAssignment.tsx index 99a97d4..e7dc364 100644 --- a/app/assignment/viewDetailsAssignment.tsx +++ b/app/assignment/viewDetailsAssignment.tsx @@ -1,4 +1,5 @@ import { defaultStyles } from '@/constants/defaultStyles'; +import { CheckAssignmentCompletion, CheckSubjectCompletion } from '@/lib/progress'; import { supabase } from '@/lib/supabase'; import type { Assignment, Task } from '@/lib/types'; import { Session } from '@supabase/supabase-js'; @@ -78,6 +79,17 @@ export default function ViewDetailsAssignment() { } Alert.alert("Assignment deleted successfully!"); + + const sId = assignment?.sId; + + if (sId) { + try { + await CheckSubjectCompletion(sId); + } catch { + Alert.alert("Failed to update subject status"); + } + } + router.back(); } } @@ -106,6 +118,15 @@ export default function ViewDetailsAssignment() { } Alert.alert("Task deleted successfully!"); + + if (aId) { + try { + await CheckAssignmentCompletion(aId); + } catch { + Alert.alert("Failed to update assignment completion state"); + } + } + GetTasks(aId); } } @@ -153,9 +174,10 @@ export default function ViewDetailsAssignment() { {assignment.isCompleted && } - + {assignment.lastChanged} + {progress}% - + - {assignment.lastChanged}