diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx
index a028b63..a3d72a9 100644
--- a/app/(tabs)/_layout.tsx
+++ b/app/(tabs)/_layout.tsx
@@ -1,6 +1,6 @@
import { supabase } from "@/lib/supabase";
import { Session } from "@supabase/supabase-js";
-import { Redirect, Tabs } from "expo-router";
+import { Tabs } from "expo-router";
import { useEffect, useState } from "react";
export default function TabLayout() {
@@ -27,9 +27,9 @@ export default function TabLayout() {
return null;
}
- if (!session) {
- return ;
- }
+ // if (!session) {
+ // return ;
+ // }
return (
diff --git a/app/(tabs)/editTask.tsx b/app/(tabs)/editTask.tsx
index 9cce4b0..6957ad5 100644
--- a/app/(tabs)/editTask.tsx
+++ b/app/(tabs)/editTask.tsx
@@ -1,80 +1,103 @@
import { defaultStyles } from '@/constants/defaultStyles';
import { supabase } from '@/lib/supabase';
-import { router, Stack, useFocusEffect, useLocalSearchParams } from 'expo-router';
+import {
+ router,
+ Stack,
+ useFocusEffect,
+ useLocalSearchParams,
+} from 'expo-router';
import { useCallback, 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,
+ StyleSheet,
+ Text,
+ TextInput,
+ TouchableWithoutFeedback,
+ View
+} from 'react-native';
export default function EditTask() {
- const [title, SetTitle] = useState('');
- const [description, SetDescription] = useState('');
- const [isCompleted, SetIsCompleted] = useState(false);
- const [deadline, SetDeadline] = useState('');
- const [isSaving, SetIsSaving] = useState(false);
- const { tId } = useLocalSearchParams();
+ const { taskId } = useLocalSearchParams<{ taskId?: string }>();
+
+ const [title, setTitle] = useState('');
+ const [description, setDescription] = useState('');
+ const [deadline, setDeadline] = useState('');
+ const [isCompleted, setIsCompleted] = useState(false);
+
+ const [isLoading, setIsLoading] = useState(false);
+ const [isSaving, setIsSaving] = useState(false);
useFocusEffect(
useCallback(() => {
- const GetTask = async () => {
- if (!tId) return;
+ const getTask = async () => {
+ if (!taskId) return;
- const { data, error } = await supabase.from("tasks").select("*").eq("tId", tId).single();
+ setIsLoading(true);
- if (error) {
- Alert.alert("Task not found");
- return;
+ try {
+ const { data, error } = await supabase
+ .from('tasks')
+ .select('*')
+ .eq('tId', taskId)
+ .single();
+
+ if (error || !data) {
+ Alert.alert('Task not found');
+ router.back();
+ return;
+ }
+
+ setTitle(data.title ?? '');
+ setDescription(data.description ?? '');
+ setDeadline(data.deadline ?? '');
+ setIsCompleted(Boolean(data.isCompleted));
+ } finally {
+ setIsLoading(false);
}
+ };
- if (data) {
- SetTitle(data.title);
- SetDescription(data.description);
- SetIsCompleted(data.isCompleted);
- SetDeadline(data.deadline);
- }
- }
- GetTask();
- }, [tId])
+ getTask();
+ }, [taskId])
);
- const EditTask = async () => {
- if(title.trim() === '' || description.trim() === '' || deadline.trim() === '') {
+ const handleSaveTask = async () => {
+ if (!title.trim() || !description.trim() || !deadline.trim()) {
Alert.alert("All fields are required!");
return;
}
-
- const { data, error: userError } = await supabase.auth.getUser();
+ setIsSaving(true);
- if(userError || !data.user) {
- router.replace("../createUser");
- return;
+ try {
+ const { data: userData, error: userError } = await supabase.auth.getUser();
+ if (userError || !userData.user) {
+ router.replace("../createUser");
+ return;
+ }
+ const { error: dbError } = await supabase.from("tasks").update({
+ title,
+ description,
+ isCompleted,
+ lastChanged: new Date().toISOString(),
+ deadline,
+ uId: userData.user.id,
+ }).eq("tId", taskId);
+
+ if (dbError) {
+ Alert.alert("Task could not be edited, please try again");
+ return;
+ }
+ Alert.alert("Task successfully edited!");
+ router.back();
+ } finally {
+ setIsSaving(false);
}
-
- SetIsSaving(true);
-
- const { error: dbError } = await supabase.from("tasks").update({
- title,
- description,
- isCompleted,
- lastChanged: new Date().toISOString(),
- deadline,
- uId: data.user.id,
- }).eq("tId", tId);
-
- if (dbError) {
- Alert.alert("Task could not be edited, please try again");
- return;
- }
-
- Alert.alert("Task successfully edited!");
-
- SetTitle('');
- SetDescription('');
- SetIsCompleted(false);
- SetDeadline('');
-
- SetIsSaving(false);
-
- router.back();
- }
+ };
return (
<>
@@ -85,49 +108,245 @@ export default function EditTask() {
}}
/>
-
- Edit Task
-
-
-
-
-
-
- SetIsCompleted(state => !state)}
- style={defaultStyles.checkboxContainer}
- >
-
- {isCompleted && ✓}
-
- {isCompleted ? 'Completed' : 'Not completed'}
-
+
-
- {isSaving && (
-
+
+
+
+ Edit Task
+ Update your task details below.
+
+ {isLoading ? (
+
+
+ Loading task...
+
+ ) : (
+ <>
+
+ Title
+
+
+
+
+ Description
+
+
+
+
+ Deadline
+
+
+
+ setIsCompleted((current) => !current)}
+ >
+
+ {isCompleted && ✓}
+
+
+
+ {isCompleted ? 'Completed' : 'Not completed'}
+
+
+
+
+
+
+ {isSaving ? 'Saving...' : 'Save Changes'}
+
+
+
+ {isSaving && (
+
+ )}
+
+ router.back()}
+ disabled={isSaving}
+ >
+ Cancel
+
+
+ >
)}
-
-
-
-
+
+
+
>
- )
+ );
}
+const styles = StyleSheet.create({
+
+ screen: {
+ flex: 1,
+ backgroundColor: 'f3f4f6'
+ },
+ container: {
+ flexGrow: 1,
+ justifyContent: 'center',
+ padding: 20,
+ },
+ card: {
+ backgroundColor: '#fff',
+ borderRadius: 8,
+ padding: 20,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 6 },
+ shadowOpacity: 0.1,
+ shadowRadius: 10,
+ elevation: 5,
+ },
+ subtitle: {
+ fontSize: 15,
+ color: '#6b7280',
+ marginBottom: 24,
+ },
+ loadingContainer: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingVertical: 40,
+ gap: 12,
+ },
+ loadingText: {
+ color: '#6b7280',
+ fontSize: 15,
+ },
+ field: {
+ marginBottom: 16,
+ },
+ label: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: '#374151',
+ marginBottom: 8,
+ },
+ input: {
+ minHeight: 50,
+ borderWidth: 1,
+ borderColor: '#d1d5db',
+ borderRadius: 12,
+ paddingHorizontal: 14,
+ paddingVertical: 12,
+ fontSize: 16,
+ color: '#111827',
+ backgroundColor: '#f9fafb',
+ },
+ textArea: {
+ minHeight: 110,
+ },
+ checkboxContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 12,
+ borderWidth: 1,
+ borderColor: '#d1d5db',
+ borderRadius: 12,
+ padding: 14,
+ marginTop: 4,
+ marginBottom: 22,
+ backgroundColor: '#f9fafb',
+ },
+ checkboxContainerActive: {
+ borderColor: '#2563eb',
+ backgroundColor: '#eff6ff',
+ },
+ checkbox: {
+ width: 24,
+ height: 24,
+ borderWidth: 2,
+ borderColor: '#9ca3af',
+ borderRadius: 6,
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: '#ffffff',
+ },
+ checkboxActive: {
+ borderColor: '#2563eb',
+ backgroundColor: '#2563eb',
+ },
+ checkboxMark: {
+ color: '#ffffff',
+ fontSize: 16,
+ fontWeight: '700',
+ },
+ checkboxLabel: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: '#111827',
+ },
+ buttonGroup: {
+ gap: 12,
+ },
+ primaryButton: {
+ height: 52,
+ borderRadius: 14,
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: '#2563eb',
+ },
+ primaryButtonText: {
+ color: '#ffffff',
+ fontSize: 16,
+ fontWeight: '700',
+ },
+ disabledButton: {
+ opacity: 0.6,
+ },
+ secondaryButton: {
+ height: 52,
+ borderRadius: 14,
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: '#e5e7eb',
+ },
+ secondaryButtonText: {
+ color: '#111827',
+ fontSize: 16,
+ fontWeight: '700',
+ },
+});
\ No newline at end of file
diff --git a/app/createUser.tsx b/app/createUser.tsx
index e20dd10..a40082c 100644
--- a/app/createUser.tsx
+++ b/app/createUser.tsx
@@ -20,7 +20,7 @@ export default function CreateUser() {
});
if (error) {
- Alert.alert("User could not be created, please try again");
+ Alert.alert(error.message, "User could not be created, please try again");
return;
}
diff --git a/lib/supabase.ts b/lib/supabase.ts
index 08bc022..1089ee8 100644
--- a/lib/supabase.ts
+++ b/lib/supabase.ts
@@ -5,6 +5,14 @@ import 'react-native-url-polyfill/auto';
const supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL!
const supabaseKey = process.env.EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
+if (!supabaseUrl) {
+ throw new Error('Missing EXPO_PUBLIC_SUPABASE_URL');
+}
+
+if (!supabaseKey) {
+ throw new Error('Missing EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY');
+}
+
const SecureStoreAdapter = {
getItem: async (key: string) => {
return await SecureStore.getItemAsync(key);