diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx
index 0e4bd89..2464474 100644
--- a/app/(tabs)/_layout.tsx
+++ b/app/(tabs)/_layout.tsx
@@ -28,9 +28,9 @@ export default function TabLayout() {
return null;
}
- // if (!session) {
- // return ;
- // }
+// if (!session) {
+// return ;
+// }
return (
diff --git a/app/(tabs)/assignments.tsx b/app/(tabs)/assignments.tsx
index 6cc5358..abeb58e 100644
--- a/app/(tabs)/assignments.tsx
+++ b/app/(tabs)/assignments.tsx
@@ -1,10 +1,16 @@
-import { defaultStyles } from "@/constants/defaultStyles";
-import { supabase } from "@/lib/supabase";
+import { defaultStyles } from '@/constants/defaultStyles';
+import { supabase } from '@/lib/supabase';
import { Ionicons } from '@expo/vector-icons';
-import { Session } from "@supabase/supabase-js";
-import { router, Stack, useFocusEffect } from "expo-router";
-import { useCallback, useEffect, useState } from "react";
-import { Alert, Button, Pressable, SectionList, Text, View } from "react-native";
+import { Session } from '@supabase/supabase-js';
+import { router, Stack, useFocusEffect } from 'expo-router';
+import { useCallback, useEffect, useState } from 'react';
+import {
+ Alert,
+ Pressable,
+ SectionList,
+ Text,
+ View,
+} from 'react-native';
type Assignment = {
aId: string;
@@ -15,36 +21,52 @@ type Assignment = {
lastChanged: string;
uId: string;
sId: string;
-}
+};
export default function Assignments() {
- const [assignments, SetAssignments] = useState([])
- const [session, SetSession] = useState(null)
+ const [assignments, SetAssignments] = useState([]);
+ const [session, SetSession] = useState(null);
const assignmentSections = [
- { title: "Upcoming Assignments", data: assignments.filter((assignment) => !assignment.isCompleted), emptyMessage: "No upcoming assignments" },
- { title: "Completed Assignments", data: assignments.filter((assignment) => assignment.isCompleted), emptyMessage: "No completed assignments" },
+ {
+ title: 'Upcoming Assignments',
+ data: assignments.filter((assignment) => !assignment.isCompleted),
+ emptyMessage: 'No upcoming 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()
- },
- [])
+ supabase.auth
+ .getSession()
+ .then(({ data }) => SetSession(data.session ?? null));
- const GetAssignments = async () => {
- const { data, error } = await supabase.from("assignments").select("*").order("deadline", { ascending: false });
+ const { data: sub } = supabase.auth.onAuthStateChange(
+ (_event, newSession) => {
+ SetSession(newSession);
+ }
+ );
+
+ return () => sub.subscription.unsubscribe();
+ }, []);
+
+ const GetAssignments = async () => {
+ const { data, error } = await supabase
+ .from('assignments')
+ .select('*')
+ .order('deadline', { ascending: false });
if (error) {
- Alert.alert("Assignments could not be fetched, please try again");
+ Alert.alert('Assignments could not be fetched, please try again');
return;
}
SetAssignments(data ?? []);
- }
+ };
useFocusEffect(
useCallback(() => {
@@ -56,92 +78,205 @@ export default function Assignments() {
const DeleteAssignment = async (aId: string) => {
Alert.alert(
- "Delete Assignment",
- "Are you sure you want to delete this assignment?",
+ 'Delete Assignment',
+ 'Are you sure you want to delete this assignment?',
[
{
- text: "Cancel",
- style: "cancel"
+ text: 'Cancel',
+ style: 'cancel',
},
{
- text: "Delete",
- style: "destructive",
+ text: 'Delete',
+ style: 'destructive',
onPress: async () => {
- const { error } = await supabase.from("assignments").delete().eq("aId", aId);
+ const { error } = await supabase
+ .from('assignments')
+ .delete()
+ .eq('aId', aId);
if (error) {
- Alert.alert("Assignment could not be deleted, please try again");
+ Alert.alert('Assignment could not be deleted, please try again');
return;
}
- Alert.alert("Assignment deleted successfully!");
+ Alert.alert('Assignment deleted successfully!');
GetAssignments();
- }
- }
+ },
+ },
]
- )
- }
+ );
+ };
return (
-
+
{
- return (
-
-
-
-
-
- )
- },
- }}
- />
-
-
-
-
- item.aId}
- renderSectionHeader={({ section: { title } }) => {title}}
- renderItem={({ item }) => {
- const isOwner = session?.user.id === item.uId;
-
- return (
-
- router.push({pathname: "/assignment/viewDetailsAssignment", params: { aId: item.aId }})}>
- {item.title}
- {item.deadline}
-
- {item.isCompleted && ✓}
-
+ headerRight: () => (
+
+
+
+
+
+ await supabase.auth.signOut()}
+ >
+
+ Logout
+
-
- {isOwner && (
-
-
- )}
- );
+ ),
}}
- renderSectionFooter={({ section }) =>
- section.data.length === 0 ? (
-
- {section.emptyMessage}
-
-
- ) : (
-
- )
- }
/>
+
+
+
+
+ Assignments
+
+
+ Track what is coming up and what you have already finished.
+
+
+
+ router.push('/assignment/createAssignment')}
+ >
+
+ Create Assignment
+
+
+
+ item.aId}
+ showsVerticalScrollIndicator={false}
+ stickySectionHeadersEnabled={false}
+ contentContainerStyle={{
+ paddingBottom: 32,
+ }}
+ 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.isCompleted && (
+
+ ✓
+
+ )}
+
+
+
+
+ {item.title}
+
+
+ {item.description ? (
+
+ {item.description}
+
+ ) : null}
+
+
+
+ Deadline: {item.deadline || 'No deadline'}
+
+
+
+
+
+
+ {isOwner && (
+
+
+ router.push({
+ pathname: '/assignment/editAssignment',
+ params: { aId: item.aId },
+ })
+ }
+ >
+
+ Edit
+
+
+
+ DeleteAssignment(item.aId)}
+ >
+
+ Delete
+
+
+
+ )}
+
+ );
+ }}
+ renderSectionFooter={({ section }) =>
+ section.data.length === 0 ? (
+
+
+ {section.emptyMessage}
+
+
+ New assignments will show up here.
+
+
+ ) : (
+
+ )
+ }
+ />
+
- )
-}
+ );
+}
\ No newline at end of file
diff --git a/app/(tabs)/subjects.tsx b/app/(tabs)/subjects.tsx
index 41b4946..5abaa9f 100644
--- a/app/(tabs)/subjects.tsx
+++ b/app/(tabs)/subjects.tsx
@@ -1,10 +1,16 @@
-import { defaultStyles } from "@/constants/defaultStyles";
-import { supabase } from "@/lib/supabase";
+import { defaultStyles } from '@/constants/defaultStyles';
+import { supabase } from '@/lib/supabase';
import { Ionicons } from '@expo/vector-icons';
-import { Session } from "@supabase/supabase-js";
-import { router, Stack, useFocusEffect } from "expo-router";
-import { useCallback, useEffect, useState } from "react";
-import { Alert, Button, Pressable, SectionList, Text, View } from "react-native";
+import { Session } from '@supabase/supabase-js';
+import { router, Stack, useFocusEffect } from 'expo-router';
+import { useCallback, useEffect, useState } from 'react';
+import {
+ Alert,
+ Pressable,
+ SectionList,
+ Text,
+ View,
+} from 'react-native';
type Subject = {
sId: string;
@@ -13,36 +19,52 @@ type Subject = {
isActive: boolean;
lastChanged: string;
uId: string;
-}
+};
export default function Subjects() {
- const [subjects, SetSubject] = useState([])
- const [session, SetSession] = useState(null)
+ const [subjects, SetSubjects] = useState([]);
+ const [session, SetSession] = useState(null);
const subjectSections = [
- { title: "Active Subjects", data: subjects.filter((subject) => !subject.isActive), emptyMessage: "No active subjects" },
- { title: "Inactive Subjects", data: subjects.filter((subject) => subject.isActive), emptyMessage: "No inactive subjects" },
+ {
+ title: 'Active Subjects',
+ data: subjects.filter((subject) => subject.isActive),
+ emptyMessage: 'No active subjects',
+ },
+ {
+ title: 'Inactive Subjects',
+ data: subjects.filter((subject) => !subject.isActive),
+ emptyMessage: 'No inactive subjects',
+ },
];
useEffect(() => {
- supabase.auth.getSession().then(({ data }) => SetSession(data.session ?? null))
- const { data: sub } = supabase.auth.onAuthStateChange((_event, newSession) => {
- SetSession(newSession)
- })
- return () => sub.subscription.unsubscribe()
- },
- [])
+ supabase.auth
+ .getSession()
+ .then(({ data }) => SetSession(data.session ?? null));
- const GetSubjects = async () => {
- const { data, error } = await supabase.from("subjects").select("*");
+ const { data: sub } = supabase.auth.onAuthStateChange(
+ (_event, newSession) => {
+ SetSession(newSession);
+ }
+ );
+
+ return () => sub.subscription.unsubscribe();
+ }, []);
+
+ const GetSubjects = async () => {
+ const { data, error } = await supabase
+ .from('subjects')
+ .select('*')
+ .order('lastChanged', { ascending: false });
if (error) {
- Alert.alert("Subjects could not be fetched, please try again");
+ Alert.alert('Subjects could not be fetched, please try again');
return;
}
- SetSubject(data ?? []);
- }
+ SetSubjects(data ?? []);
+ };
useFocusEffect(
useCallback(() => {
@@ -54,91 +76,206 @@ export default function Subjects() {
const DeleteSubject = async (sId: string) => {
Alert.alert(
- "Delete Subject",
- "Are you sure you want to delete this subject?",
+ 'Delete Subject',
+ 'Are you sure you want to delete this subject?',
[
{
- text: "Cancel",
- style: "cancel"
+ text: 'Cancel',
+ style: 'cancel',
},
{
- text: "Delete",
- style: "destructive",
+ text: 'Delete',
+ style: 'destructive',
onPress: async () => {
- const { error } = await supabase.from("subjects").delete().eq("sId", sId);
+ const { error } = await supabase
+ .from('subjects')
+ .delete()
+ .eq('sId', sId);
if (error) {
- Alert.alert("Subject could not be deleted, please try again");
+ Alert.alert('Subject could not be deleted, please try again');
return;
}
- Alert.alert("Subject deleted successfully!");
+ Alert.alert('Subject deleted successfully!');
GetSubjects();
- }
- }
+ },
+ },
]
- )
- }
+ );
+ };
return (
-
+
{
- return (
-
-
-
-
- await supabase.auth.signOut()} />
-
- )
- },
- }}
- />
-
-
- router.push("/subject/createSubject")} />
-
-
- item.sId}
- renderSectionHeader={({ section: { title } }) => {title}}
- renderItem={({ item }) => {
- const isOwner = session?.user.id === item.uId;
-
- return (
-
- router.push({pathname: "/subject/viewDetailsSubject", params: { sId: item.sId }})}>
- {item.title}
-
- {item.isActive && ✓}
-
+ headerRight: () => (
+
+
+
+
+
+ await supabase.auth.signOut()}
+ >
+
+ Logout
+
-
- {isOwner && (
-
- router.push({pathname: "/subject/editSubject", params: { sId: item.sId }})} />
- DeleteSubject(item.sId)} />
-
- )}
- );
+ ),
}}
- renderSectionFooter={({ section }) =>
- section.data.length === 0 ? (
-
- {section.emptyMessage}
-
-
- ) : (
-
- )
- }
/>
+
+
+
+
+ Subjects
+
+
+ Organize your study work by subject, then break it into assignments
+ and tasks.
+
+
+
+ router.push('/subject/createSubject')}
+ >
+
+ Create Subject
+
+
+
+ item.sId}
+ showsVerticalScrollIndicator={false}
+ stickySectionHeadersEnabled={false}
+ contentContainerStyle={{
+ paddingBottom: 32,
+ }}
+ renderSectionHeader={({ section: { title, data } }) => (
+
+
+ {title}
+
+
+
+
+ {data.length}
+
+
+
+ )}
+ renderItem={({ item }) => {
+ const isOwner = session?.user.id === item.uId;
+
+ return (
+
+
+ router.push({
+ pathname: '/subject/viewDetailsSubject',
+ params: { sId: item.sId },
+ })
+ }
+ >
+
+
+ {item.isActive && (
+
+ ✓
+
+ )}
+
+
+
+
+ {item.title}
+
+
+ {item.description ? (
+
+ {item.description}
+
+ ) : null}
+
+
+
+ {item.isActive ? 'Active' : 'Inactive'}
+
+
+
+
+
+
+ {isOwner && (
+
+
+ router.push({
+ pathname: '/subject/editSubject',
+ params: { sId: item.sId },
+ })
+ }
+ >
+
+ Edit
+
+
+
+ DeleteSubject(item.sId)}
+ >
+
+ Delete
+
+
+
+ )}
+
+ );
+ }}
+ renderSectionFooter={({ section }) =>
+ section.data.length === 0 ? (
+
+
+ {section.emptyMessage}
+
+
+ Subjects you create will show up here.
+
+
+ ) : (
+
+ )
+ }
+ />
+
- )
-}
+ );
+}
\ No newline at end of file
diff --git a/app/(tabs)/tasks.tsx b/app/(tabs)/tasks.tsx
index 47ed0ac..447c948 100644
--- a/app/(tabs)/tasks.tsx
+++ b/app/(tabs)/tasks.tsx
@@ -1,10 +1,16 @@
-import { defaultStyles } from "@/constants/defaultStyles";
-import { supabase } from "@/lib/supabase";
+import { defaultStyles } from '@/constants/defaultStyles';
+import { supabase } from '@/lib/supabase';
import { Ionicons } from '@expo/vector-icons';
-import { Session } from "@supabase/supabase-js";
-import { router, Stack, useFocusEffect } from "expo-router";
-import { useCallback, useEffect, useState } from "react";
-import { Alert, Button, Pressable, SectionList, Text, View } from "react-native";
+import { Session } from '@supabase/supabase-js';
+import { router, Stack, useFocusEffect } from 'expo-router';
+import { useCallback, useEffect, useState } from 'react';
+import {
+ Alert,
+ Pressable,
+ SectionList,
+ Text,
+ View,
+} from 'react-native';
type Task = {
tId: string;
@@ -14,36 +20,49 @@ type Task = {
lastChanged: string;
uId: string;
aId: string;
-}
+};
export default function Tasks() {
- const [tasks, SetTasks] = useState([])
- const [session, SetSession] = useState(null)
+ const [tasks, SetTasks] = useState([]);
+ const [session, SetSession] = useState(null);
const taskSections = [
- { title: "Upcoming Tasks", data: tasks.filter((task) => !task.isCompleted), emptyMessage: "No upcoming tasks" },
- { title: "Completed Tasks", data: tasks.filter((task) => task.isCompleted), emptyMessage: "No completed tasks" },
+ {
+ title: 'Upcoming Tasks',
+ data: tasks.filter((task) => !task.isCompleted),
+ emptyMessage: 'No upcoming tasks',
+ },
+ {
+ title: 'Completed Tasks',
+ data: tasks.filter((task) => task.isCompleted),
+ emptyMessage: 'No completed tasks',
+ },
];
useEffect(() => {
- supabase.auth.getSession().then(({ data }) => SetSession(data.session ?? null))
- const { data: sub } = supabase.auth.onAuthStateChange((_event, newSession) => {
- SetSession(newSession)
- })
- return () => sub.subscription.unsubscribe()
- },
- [])
+ supabase.auth
+ .getSession()
+ .then(({ data }) => SetSession(data.session ?? null));
- const GetTasks = async () => {
- const { data, error } = await supabase.from("tasks").select("*");
+ const { data: sub } = supabase.auth.onAuthStateChange(
+ (_event, newSession) => {
+ SetSession(newSession);
+ }
+ );
+
+ return () => sub.subscription.unsubscribe();
+ }, []);
+
+ const GetTasks = async () => {
+ const { data, error } = await supabase.from('tasks').select('*');
if (error) {
- Alert.alert("Tasks could not be fetched, please try again");
+ Alert.alert('Tasks could not be fetched, please try again');
return;
}
SetTasks(data ?? []);
- }
+ };
useFocusEffect(
useCallback(() => {
@@ -55,91 +74,205 @@ export default function Tasks() {
const DeleteTask = async (tId: string) => {
Alert.alert(
- "Delete Task",
- "Are you sure you want to delete this task?",
+ 'Delete Task',
+ 'Are you sure you want to delete this task?',
[
{
- text: "Cancel",
- style: "cancel"
+ text: 'Cancel',
+ style: 'cancel',
},
{
- text: "Delete",
- style: "destructive",
+ text: 'Delete',
+ style: 'destructive',
onPress: async () => {
- const { error } = await supabase.from("tasks").delete().eq("tId", tId);
+ const { error } = await supabase
+ .from('tasks')
+ .delete()
+ .eq('tId', tId);
if (error) {
- Alert.alert("Task could not be deleted, please try again");
+ Alert.alert('Task could not be deleted, please try again');
return;
}
- Alert.alert("Task deleted successfully!");
+ Alert.alert('Task deleted successfully!');
GetTasks();
- }
- }
+ },
+ },
]
- )
- }
+ );
+ };
return (
-
+
{
- return (
-
-
-
-
- await supabase.auth.signOut()} />
-
- )
- },
- }}
- />
-
-
- router.push("/task/createTask")} />
-
-
- item.tId}
- renderSectionHeader={({ section: { title } }) => {title}}
- renderItem={({ item }) => {
- const isOwner = session?.user.id === item.uId;
-
- return (
-
- router.push({pathname: "/task/viewDetailsTask", params: { tId: item.tId }})}>
- {item.title}
-
- {item.isCompleted && ✓}
-
+ headerRight: () => (
+
+
+
- {isOwner && (
-
- router.push({pathname: "/task/editTask", params: { tId: item.tId }})} />
- DeleteTask(item.tId)} />
-
- )}
+ await supabase.auth.signOut()}
+ >
+
+ Logout
+
+
- );
+ ),
}}
- renderSectionFooter={({ section }) =>
- section.data.length === 0 ? (
-
- {section.emptyMessage}
-
-
- ) : (
-
- )
- }
/>
+
+
+
+
+ Tasks
+
+
+ Break assignments into small steps and keep your progress clear.
+
+
+
+ router.push('/task/createTask')}
+ >
+
+ Create Task
+
+
+
+ item.tId}
+ showsVerticalScrollIndicator={false}
+ stickySectionHeadersEnabled={false}
+ contentContainerStyle={{
+ paddingBottom: 32,
+ }}
+ renderSectionHeader={({ section: { title, data } }) => (
+
+
+ {title}
+
+
+
+
+ {data.length}
+
+
+
+ )}
+ renderItem={({ item }) => {
+ const isOwner = session?.user.id === item.uId;
+
+ return (
+
+
+ router.push({
+ pathname: '/task/viewDetailsTask',
+ params: { tId: item.tId },
+ })
+ }
+ >
+
+
+ {item.isCompleted && (
+
+ ✓
+
+ )}
+
+
+
+
+ {item.title}
+
+
+ {item.description ? (
+
+ {item.description}
+
+ ) : null}
+
+
+
+ {item.isCompleted ? 'Completed' : 'In progress'}
+
+
+
+
+
+
+ {isOwner && (
+
+
+ router.push({
+ pathname: '/task/editTask',
+ params: { tId: item.tId },
+ })
+ }
+ >
+
+ Edit
+
+
+
+ DeleteTask(item.tId)}
+ >
+
+ Delete
+
+
+
+ )}
+
+ );
+ }}
+ renderSectionFooter={({ section }) =>
+ section.data.length === 0 ? (
+
+
+ {section.emptyMessage}
+
+
+ Tasks for this assignment will show up here.
+
+
+ ) : (
+
+ )
+ }
+ />
+
- )
-}
+ );
+}
\ No newline at end of file
diff --git a/app/assignment/createAssignment.tsx b/app/assignment/createAssignment.tsx
index fc7df63..d6b9841 100644
--- a/app/assignment/createAssignment.tsx
+++ b/app/assignment/createAssignment.tsx
@@ -2,10 +2,23 @@ import { defaultStyles } from '@/constants/defaultStyles';
import { supabase } from '@/lib/supabase';
import { router, Stack, useLocalSearchParams } from 'expo-router';
import { useState } from 'react';
-import { ActivityIndicator, Alert, Keyboard, KeyboardAvoidingView, Platform, Pressable, ScrollView, Text, TextInput, TouchableWithoutFeedback, View } from 'react-native';
+import {
+ ActivityIndicator,
+ Alert,
+ Keyboard,
+ KeyboardAvoidingView,
+ Platform,
+ Pressable,
+ ScrollView,
+ Text,
+ TextInput,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
export default function CreateAssignment() {
const sId = (useLocalSearchParams().sId as string) ?? null;
+
const [title, SetTitle] = useState('');
const [description, SetDescription] = useState('');
const [deadline, SetDeadline] = useState('');
@@ -13,171 +26,188 @@ export default function CreateAssignment() {
const [isSaving, SetIsSaving] = useState(false);
const CreateAssignment = async () => {
- if(title.trim() === '') {
- Alert.alert("Title is required!");
+ if (title.trim() === '') {
+ Alert.alert('Title is required!');
return;
}
-
+
const { data, error: userError } = await supabase.auth.getUser();
- if(userError || !data.user) {
- router.replace("../createUser");
+ if (userError || !data.user) {
+ router.replace('../createUser');
return;
- }
+ }
SetIsSaving(true);
- const { error: dbError } = await supabase.from("assignments").insert({
- title,
- description,
- deadline,
+ const { error: dbError } = await supabase.from('assignments').insert({
+ title: title.trim(),
+ description: description.trim(),
+ deadline: deadline.trim(),
isCompleted,
lastChanged: new Date().toISOString(),
uId: data.user.id,
- sId: sId,
+ sId,
});
if (dbError) {
- Alert.alert("Assignment could not be created, please try again");
+ SetIsSaving(false);
+ Alert.alert('Assignment could not be created, please try again');
return;
}
- Alert.alert("Assignment successfully created!");
+ Alert.alert('Assignment successfully created!');
SetTitle('');
SetDescription('');
+ SetDeadline('');
SetIsCompleted(false);
-
SetIsSaving(false);
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';
return (
<>
-
- Create New Assignment
-
-
-
-
-
-
- Title
-
-
-
+
+
+
+
+
+ Create Assignment
+
+
+ Add a new assignment to keep your subject organized.
+
+
-
-
- Description
-
-
-
-
-
-
- Deadline
-
-
-
-
- SetIsCompleted((current) => !current)}
- >
-
- {isCompleted && (
- ✓
- )}
-
-
-
- {isCompleted ? 'Completed' : 'Not completed'}
-
-
-
-
-
- {isSaving ? 'Saving...' : 'Save Changes'}
-
-
-
- {isSaving && (
-
-
-
- )}
-
- router.back()}
- disabled={isSaving}
- >
-
- Cancel
-
-
+
+
+ Title
+
-
-
-
-
+
+
+ Description
+
+
+
+
+ Deadline
+
+
+
+ SetIsCompleted((current) => !current)}
+ disabled={isSaving}
+ >
+
+ {isCompleted && (
+
+ ✓
+
+ )}
+
+
+
+
+ Mark as completed
+
+
+ You can change this later.
+
+
+
+
+
+ {isSaving ? (
+
+
+
+ Creating...
+
+
+ ) : (
+
+ Create Assignment
+
+ )}
+
+
+ router.back()}
+ disabled={isSaving}
+ >
+
+ Cancel
+
+
+
+
+
+
>
);
}
\ No newline at end of file
diff --git a/app/subject/createSubject.tsx b/app/subject/createSubject.tsx
index 33d95df..5c13e01 100644
--- a/app/subject/createSubject.tsx
+++ b/app/subject/createSubject.tsx
@@ -2,99 +2,194 @@ import { defaultStyles } from '@/constants/defaultStyles';
import { supabase } from '@/lib/supabase';
import { router, Stack } from 'expo-router';
import { useState } from 'react';
-import { ActivityIndicator, Alert, Button, Keyboard, KeyboardAvoidingView, Platform, Pressable, Text, TextInput, TouchableWithoutFeedback, View } from 'react-native';
+import {
+ ActivityIndicator,
+ Alert,
+ Keyboard,
+ KeyboardAvoidingView,
+ Platform,
+ Pressable,
+ ScrollView,
+ Text,
+ TextInput,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
-export default function CreateTask() {
+export default function CreateSubject() {
const [title, SetTitle] = useState('');
const [description, SetDescription] = useState('');
const [isActive, SetIsActive] = useState(true);
const [isSaving, SetIsSaving] = useState(false);
const CreateSubject = async () => {
- if(title.trim() === '') {
- Alert.alert("Title is required!");
+ if (title.trim() === '') {
+ Alert.alert('Title is required!');
return;
}
-
+
const { data, error: userError } = await supabase.auth.getUser();
- if(userError || !data.user) {
- router.replace("../createUser");
+ if (userError || !data.user) {
+ router.replace('../createUser');
return;
- }
+ }
SetIsSaving(true);
- const { error: dbError } = await supabase.from("subjects").insert({
- title,
- description,
+ const { error: dbError } = await supabase.from('subjects').insert({
+ title: title.trim(),
+ description: description.trim(),
isActive,
lastChanged: new Date().toISOString(),
uId: data.user.id,
});
if (dbError) {
- Alert.alert("Subject could not be created, please try again");
+ SetIsSaving(false);
+ Alert.alert('Subject could not be created, please try again');
return;
}
- Alert.alert("Subject successfully created!");
+ Alert.alert('Subject successfully created!');
SetTitle('');
SetDescription('');
- SetIsActive(false);
-
+ SetIsActive(true);
SetIsSaving(false);
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';
return (
<>
-
- Create New Subject
-
-
-
-
-
+
+
+
+
+
+ Create Subject
+
+
+ Add a subject to organize your assignments and study tasks.
+
+
+
+
+
+ Title
+
+
+
+
+ Description
+
+
+
SetIsActive(state => !state)}
- style={defaultStyles.checkboxContainer}
+ onPress={() => 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 && ✓}
+
+ {isActive && (
+
+ ✓
+
+ )}
+
+
+
+
+ Active subject
+
+
+ Active subjects appear in your main study workflow.
+
- {isActive ? 'Active' : 'Inactive'}
-
- {isSaving && (
-
- )}
- router.back()} />
-
-
-
-
- >
- )
-}
+
+ {isSaving ? (
+
+
+
+ Creating...
+
+
+ ) : (
+
+ Create Subject
+
+ )}
+
+ router.back()}
+ disabled={isSaving}
+ >
+
+ Cancel
+
+
+
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/app/task/createTask.tsx b/app/task/createTask.tsx
index af08418..5f73004 100644
--- a/app/task/createTask.tsx
+++ b/app/task/createTask.tsx
@@ -2,102 +2,197 @@ import { defaultStyles } from '@/constants/defaultStyles';
import { supabase } from '@/lib/supabase';
import { router, Stack, useLocalSearchParams } from 'expo-router';
import { useState } from 'react';
-import { ActivityIndicator, Alert, Button, Keyboard, KeyboardAvoidingView, Platform, Pressable, Text, TextInput, TouchableWithoutFeedback, View } from 'react-native';
+import {
+ ActivityIndicator,
+ Alert,
+ Keyboard,
+ KeyboardAvoidingView,
+ Platform,
+ Pressable,
+ ScrollView,
+ Text,
+ TextInput,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
export default function CreateTask() {
const aId = (useLocalSearchParams().aId as string) ?? null;
+
const [title, SetTitle] = useState('');
const [description, SetDescription] = useState('');
const [isCompleted, SetIsCompleted] = useState(false);
const [isSaving, SetIsSaving] = useState(false);
const CreateTask = async () => {
- if(title.trim() === '') {
- Alert.alert("Title is required!");
+ if (title.trim() === '') {
+ Alert.alert('Title is required!');
return;
}
-
+
const { data, error: userError } = await supabase.auth.getUser();
- if(userError || !data.user) {
- router.replace("../createUser");
+ if (userError || !data.user) {
+ router.replace('../createUser');
return;
- }
+ }
SetIsSaving(true);
- const { error: dbError } = await supabase.from("tasks").insert({
- title,
- description,
+ const { error: dbError } = await supabase.from('tasks').insert({
+ title: title.trim(),
+ description: description.trim(),
isCompleted,
lastChanged: new Date().toISOString(),
uId: data.user.id,
- aId: aId,
+ aId,
});
if (dbError) {
- Alert.alert("Task could not be created, please try again");
+ SetIsSaving(false);
+ Alert.alert('Task could not be created, please try again');
return;
}
- Alert.alert("Task successfully created!");
+ Alert.alert('Task successfully created!');
SetTitle('');
SetDescription('');
SetIsCompleted(false);
-
SetIsSaving(false);
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';
return (
<>
-
- Create New Task
-
-
-
-
-
+
+
+
+
+
+ Create Task
+
+
+ Add a small step to move this assignment forward.
+
+
+
+
+
+ Title
+
+
+
+
+ Description
+
+
SetIsCompleted(state => !state)}
- style={defaultStyles.checkboxContainer}
+ onPress={() => 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 && ✓}
+
+ {isCompleted && (
+
+ ✓
+
+ )}
+
+
+
+
+ Mark as completed
+
+
+ You can change this later.
+
- {isCompleted ? 'Completed' : 'Not completed'}
-
- {isSaving && (
-
- )}
- router.back()} />
-
-
-
-
- >
- )
-}
+
+ {isSaving ? (
+
+
+
+ Creating...
+
+
+ ) : (
+
+ Create Task
+
+ )}
+
+ router.back()}
+ disabled={isSaving}
+ >
+
+ Cancel
+
+
+
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 39c47cc..5f76e3e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,6 +7,7 @@
"": {
"name": "study-sprint",
"version": "1.0.0",
+ "hasInstallScript": true,
"dependencies": {
"@expo/vector-icons": "^15.0.3",
"@react-navigation/bottom-tabs": "^7.4.0",
diff --git a/tailwind.config.js b/tailwind.config.js
index 680d8ea..11597db 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -10,59 +10,60 @@ module.exports = {
extend: {
colors: {
app: {
- bg: "var(--color-bg)",
- surface: "var(--color-surface)",
- subtle: "var(--color-subtle)",
- border: "var(--color-border)",
+ bg: '#F7F5EF',
+ surface: '#FFFFFF',
+ subtle: '#EFEBE3',
+ border: '#DDD6C8',
},
text: {
- main: "var(--color-text-main)",
- secondary: "var(--color-text-secondary)",
- muted: "var(--color-text-muted)",
- inverse: "var(--color-text-inverse)",
+ main: '#1F2933',
+ secondary: '#52616B',
+ muted: '#9AA6B2',
+ inverse: '#FFFFFF',
},
accent: {
- DEFAULT: "var(--color-accent)",
- soft: "var(--color-accent-soft)",
- hover: "var(--color-accent-hover)",
+ DEFAULT: '#3B82A0',
+ soft: '#DCEFF5',
+ hover: '#2F6F88',
+ disabled: '#9CC7D6',
},
status: {
- success: "var(--color-success)",
- warning: "var(--color-warning)",
- danger: "var(--color-danger)",
+ success: '#15803D',
+ warning: '#B7791F',
+ danger: '#B91C1C',
},
subject: {
blue: {
- bg: "var(--subject-blue-bg)",
- text: "var(--subject-blue-text)",
+ bg: '#DCEFF5',
+ text: '#2F6F88',
},
emerald: {
- bg: "var(--subject-emerald-bg)",
- text: "var(--subject-emerald-text)",
+ bg: '#DDEFE5',
+ text: '#2F7D55',
},
amber: {
- bg: "var(--subject-amber-bg)",
- text: "var(--subject-amber-text)",
+ bg: '#F6E8C6',
+ text: '#9A6A16',
},
violet: {
- bg: "var(--subject-violet-bg)",
- text: "var(--subject-violet-text)",
+ bg: '#E9E2F5',
+ text: '#6D4BA3',
},
cyan: {
- bg: "var(--subject-cyan-bg)",
- text: "var(--subject-cyan-text)",
+ bg: '#DDF0EF',
+ text: '#287C7A',
},
rose: {
- bg: "var(--subject-rose-bg)",
- text: "var(--subject-rose-text)",
+ bg: '#F4E1DF',
+ text: '#9B4A43',
},
slate: {
- bg: "var(--subject-slate-bg)",
- text: "var(--subject-slate-text)",
+ bg: '#E8E4DA',
+ text: '#52616B',
},
},
},