diff --git a/app/(tabs)/settings.tsx b/app/(tabs)/settings.tsx
deleted file mode 100644
index d3da691..0000000
--- a/app/(tabs)/settings.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { StyleSheet, Image, Platform } from 'react-native';
-import ParallaxScrollView from '@/components/default/ParallaxScrollView';
-import { ThemedText, ThemedView } from '@/components/theme';
-import { IconSymbol } from '@/components/ui/IconSymbol';
-import Logout_Button from '@/components/auth/Logout_Button';
-
-const TabTwoScreen = () => {
- return (
-
- }
- headerTitle={
-
- Settings
-
- }
- >
-
-
- );
-};
-export default TabTwoScreen;
-
-const styles = StyleSheet.create({
- headerImage: {
- color: '#808080',
- bottom: 6,
- left: 38,
- position: 'absolute',
- },
- headerTitle: {
- position: 'absolute',
- bottom: 20,
- left: 16,
- right: 0,
- textAlign: 'center',
- fontSize: 48,
- lineHeight: 64,
- fontWeight: 'bold',
- },
- titleContainer: {
- flexDirection: 'row',
- gap: 8,
- },
-});
diff --git a/app/(tabs)/settings/_layout.tsx b/app/(tabs)/settings/_layout.tsx
new file mode 100644
index 0000000..c828882
--- /dev/null
+++ b/app/(tabs)/settings/_layout.tsx
@@ -0,0 +1,39 @@
+import { Stack } from 'expo-router';
+import { useColorScheme } from '@/hooks/useColorScheme';
+import { Colors } from '@/constants/Colors';
+
+export default function SettingsLayout() {
+ const scheme = useColorScheme() ?? 'dark';
+
+ return (
+
+
+
+ {/* Add more screens as needed */}
+
+ );
+}
diff --git a/app/(tabs)/settings/index.tsx b/app/(tabs)/settings/index.tsx
new file mode 100644
index 0000000..1f7dd11
--- /dev/null
+++ b/app/(tabs)/settings/index.tsx
@@ -0,0 +1,91 @@
+import { StyleSheet, TouchableOpacity } from 'react-native';
+import { useRouter } from 'expo-router';
+import ParallaxScrollView from '@/components/default/ParallaxScrollView';
+import { ThemedText, ThemedTextButton, ThemedView } from '@/components/theme';
+import { IconSymbol } from '@/components/ui/IconSymbol';
+import Logout_Button from '@/components/auth/Logout_Button';
+
+const SettingsScreen = () => {
+ const router = useRouter();
+
+ return (
+
+ }
+ headerTitle={
+
+ Settings
+
+ }
+ >
+
+ router.push('/settings/profile')}
+ >
+
+
+ Profile
+ Name, photo, email
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default SettingsScreen;
+
+const styles = StyleSheet.create({
+ headerImage: {
+ color: '#808080',
+ bottom: 6,
+ left: 38,
+ position: 'absolute',
+ },
+ headerTitle: {
+ position: 'absolute',
+ bottom: 20,
+ left: 16,
+ right: 0,
+ textAlign: 'center',
+ fontSize: 48,
+ lineHeight: 64,
+ fontWeight: 'bold',
+ },
+ section: {
+ marginVertical: 16,
+ borderRadius: 10,
+ overflow: 'hidden',
+ },
+ settingItem: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ padding: 16,
+ backgroundColor: 'rgba(200, 200, 200, 0.1)',
+ marginBottom: 1,
+ },
+ icon: {
+ marginRight: 16,
+ },
+ settingContent: {
+ backgroundColor: 'transparent',
+ flex: 1,
+ },
+ settingTitle: {
+ fontSize: 17,
+ fontWeight: '500',
+ },
+ settingSubtitle: {
+ fontSize: 14,
+ opacity: 0.6,
+ marginTop: 4,
+ },
+});
diff --git a/app/(tabs)/settings/profile.tsx b/app/(tabs)/settings/profile.tsx
new file mode 100644
index 0000000..dee08eb
--- /dev/null
+++ b/app/(tabs)/settings/profile.tsx
@@ -0,0 +1,173 @@
+import React, { useState, useEffect } from 'react';
+import { StyleSheet, TouchableOpacity, Image, Alert, ActivityIndicator } from 'react-native';
+import * as ImagePicker from 'expo-image-picker';
+import { supabase } from '@/lib/supabase';
+import { ThemedView, ThemedText, ThemedTextInput } from '@/components/theme';
+import { IconSymbol } from '@/components/ui/IconSymbol';
+
+export default function ProfileScreen() {
+ const [loading, setLoading] = useState(false);
+ const [fullName, setFullName] = useState('');
+ const [email, setEmail] = useState('');
+ const [avatar, setAvatar] = useState(null);
+
+ useEffect(() => {
+ fetchUserProfile();
+ }, []);
+
+ const fetchUserProfile = async () => {
+ setLoading(true);
+ try {
+ const { data: { user } } = await supabase.auth.getUser();
+
+ if (user) {
+ const { data, error } = await supabase
+ .from('profiles')
+ .select('*')
+ .eq('id', user.id)
+ .single();
+
+ if (data) {
+ setFullName(data.full_name || '');
+ setEmail(data.email || '');
+ setAvatar(data.avatar_url || null);
+ }
+ }
+ } catch (error) {
+ console.error('Error fetching profile:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const updateProfile = async () => {
+ setLoading(true);
+ try {
+ const { data: { user } } = await supabase.auth.getUser();
+
+ if (!user) throw new Error('User not found');
+
+ const updates = {
+ id: user.id,
+ full_name: fullName,
+ email,
+ updated_at: new Date(),
+ };
+
+ const { error } = await supabase
+ .from('profiles')
+ .upsert(updates);
+
+ if (error) throw error;
+
+ Alert.alert('Success', 'Profile updated successfully!');
+ } catch (error) {
+ Alert.alert('Error updating profile', error.message);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // Add image picking functionality here (similar to previous example)
+
+ return (
+
+
+ {avatar ? (
+
+ ) : (
+
+
+
+ )}
+ Change Photo
+
+
+
+ Full Name
+
+
+ Email
+
+
+
+
+ {loading ? (
+
+ ) : (
+ Save Changes
+ )}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 16,
+ },
+ avatarContainer: {
+ alignItems: 'center',
+ marginTop: 20,
+ marginBottom: 30,
+ },
+ avatar: {
+ width: 120,
+ height: 120,
+ borderRadius: 60,
+ },
+ avatarPlaceholder: {
+ width: 120,
+ height: 120,
+ borderRadius: 60,
+ backgroundColor: '#E1E1E1',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ changePhotoText: {
+ marginTop: 8,
+ color: '#007AFF',
+ fontSize: 16,
+ },
+ formSection: {
+ marginBottom: 30,
+ },
+ label: {
+ marginBottom: 8,
+ fontSize: 16,
+ },
+ input: {
+ fontSize: 16,
+ paddingVertical: 12,
+ paddingHorizontal: 10,
+ borderRadius: 8,
+ marginBottom: 20,
+ },
+ saveButton: {
+ backgroundColor: '#007AFF',
+ paddingVertical: 14,
+ borderRadius: 8,
+ alignItems: 'center',
+ },
+ saveButtonText: {
+ color: '#fff',
+ fontSize: 16,
+ },
+});
diff --git a/package-lock.json b/package-lock.json
index 9730a1b..a3cd810 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -29,6 +29,7 @@
"expo-font": "~13.0.3",
"expo-haptics": "~14.0.1",
"expo-image": "~2.0.6",
+ "expo-image-picker": "~16.0.6",
"expo-insights": "~0.8.2",
"expo-linking": "~7.0.5",
"expo-location": "~18.0.7",
@@ -8457,6 +8458,27 @@
}
}
},
+ "node_modules/expo-image-loader": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-5.0.0.tgz",
+ "integrity": "sha512-Eg+5FHtyzv3Jjw9dHwu2pWy4xjf8fu3V0Asyy42kO+t/FbvW/vjUixpTjPtgKQLQh+2/9Nk4JjFDV6FwCnF2ZA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-image-picker": {
+ "version": "16.0.6",
+ "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-16.0.6.tgz",
+ "integrity": "sha512-HN4xZirFjsFDIsWFb12AZh19fRzuvZjj2ll17cGr19VNRP06S/VPQU3Tdccn5vwUzQhOBlLu704CnNm278boiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "expo-image-loader": "~5.0.0"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
"node_modules/expo-insights": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/expo-insights/-/expo-insights-0.8.2.tgz",
diff --git a/package.json b/package.json
index 9454b3b..d7b3762 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,8 @@
"react-native-svg": "15.8.0",
"react-native-svg-transformer": "^1.5.0",
"react-native-web": "~0.19.13",
- "react-native-webview": "13.12.5"
+ "react-native-webview": "13.12.5",
+ "expo-image-picker": "~16.0.6"
},
"devDependencies": {
"@babel/core": "^7.25.2",