Skip to content

Commit e201e83

Browse files
This commit introduces a new "Account" page to the application.
- An "Account" tab has been added to the main navigation. - The new screen displays user information and a list of options. - You can now edit your profile information (name). - The logout functionality is accessible from this page. - Placeholders are included for future features like email settings and feedback.
1 parent 57e23d5 commit e201e83

File tree

6 files changed

+193
-1
lines changed

6 files changed

+193
-1
lines changed

frontend/api/auth.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@ export const login = (email, password) => {
1616
export const signup = (name, email, password) => {
1717
return apiClient.post('/auth/signup/email', { name, email, password });
1818
};
19+
20+
export const updateUser = (token, userData) => {
21+
return apiClient.patch('/user/', userData, {
22+
headers: {
23+
Authorization: `Bearer ${token}`,
24+
},
25+
});
26+
};

frontend/context/AuthContext.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,12 @@ export const AuthProvider = ({ children }) => {
4242
setUser(null);
4343
};
4444

45+
const updateUserInContext = (updatedUser) => {
46+
setUser(updatedUser);
47+
};
48+
4549
return (
46-
<AuthContext.Provider value={{ user, token, isLoading, login, signup, logout }}>
50+
<AuthContext.Provider value={{ user, token, isLoading, login, signup, logout, updateUserInContext }}>
4751
{children}
4852
</AuthContext.Provider>
4953
);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react';
2+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
3+
import AccountScreen from '../screens/AccountScreen';
4+
import EditProfileScreen from '../screens/EditProfileScreen';
5+
6+
const Stack = createNativeStackNavigator();
7+
8+
const AccountStackNavigator = () => {
9+
return (
10+
<Stack.Navigator>
11+
<Stack.Screen name="AccountRoot" component={AccountScreen} options={{ headerShown: false }}/>
12+
<Stack.Screen name="EditProfile" component={EditProfileScreen} options={{ headerShown: false }} />
13+
</Stack.Navigator>
14+
);
15+
};
16+
17+
export default AccountStackNavigator;

frontend/navigation/MainNavigator.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
33
import { MaterialCommunityIcons } from '@expo/vector-icons';
44
import GroupsStackNavigator from './GroupsStackNavigator';
55
import FriendsScreen from '../screens/FriendsScreen';
6+
import AccountStackNavigator from './AccountStackNavigator';
67

78
const Tab = createBottomTabNavigator();
89

@@ -27,6 +28,15 @@ const MainNavigator = () => {
2728
),
2829
}}
2930
/>
31+
<Tab.Screen
32+
name="Account"
33+
component={AccountStackNavigator}
34+
options={{
35+
tabBarIcon: ({ color, size }) => (
36+
<MaterialCommunityIcons name="account-cog" color={color} size={size} />
37+
),
38+
}}
39+
/>
3040
</Tab.Navigator>
3141
);
3242
};

frontend/screens/AccountScreen.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import React, { useContext } from 'react';
2+
import { View, StyleSheet, Alert } from 'react-native';
3+
import { Text, Appbar, Avatar, List, Divider } from 'react-native-paper';
4+
import { AuthContext } from '../context/AuthContext';
5+
6+
const AccountScreen = ({ navigation }) => {
7+
const { user, logout } = useContext(AuthContext);
8+
9+
const handleLogout = () => {
10+
logout();
11+
};
12+
13+
const handleComingSoon = () => {
14+
Alert.alert('Coming Soon', 'This feature is not yet implemented.');
15+
};
16+
17+
return (
18+
<View style={styles.container}>
19+
<Appbar.Header>
20+
<Appbar.Content title="Account" />
21+
</Appbar.Header>
22+
<View style={styles.content}>
23+
<View style={styles.profileSection}>
24+
<Avatar.Text size={80} label={user?.name?.charAt(0) || 'A'} />
25+
<Text variant="headlineSmall" style={styles.name}>{user?.name}</Text>
26+
<Text variant="bodyLarge" style={styles.email}>{user?.email}</Text>
27+
</View>
28+
29+
<List.Section>
30+
<List.Item
31+
title="Edit Profile"
32+
left={() => <List.Icon icon="account-edit" />}
33+
onPress={() => navigation.navigate('EditProfile')}
34+
/>
35+
<Divider />
36+
<List.Item
37+
title="Email Settings"
38+
left={() => <List.Icon icon="email-settings" />}
39+
onPress={handleComingSoon}
40+
/>
41+
<Divider />
42+
<List.Item
43+
title="Send Feedback"
44+
left={() => <List.Icon icon="feedback" />}
45+
onPress={handleComingSoon}
46+
/>
47+
<Divider />
48+
<List.Item
49+
title="Logout"
50+
left={() => <List.Icon icon="logout" />}
51+
onPress={handleLogout}
52+
/>
53+
</List.Section>
54+
</View>
55+
</View>
56+
);
57+
};
58+
59+
const styles = StyleSheet.create({
60+
container: {
61+
flex: 1,
62+
},
63+
content: {
64+
padding: 16,
65+
},
66+
profileSection: {
67+
alignItems: 'center',
68+
marginBottom: 24,
69+
},
70+
name: {
71+
marginTop: 16,
72+
},
73+
email: {
74+
marginTop: 4,
75+
color: 'gray',
76+
}
77+
});
78+
79+
export default AccountScreen;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import React, { useState, useContext } from 'react';
2+
import { View, StyleSheet, Alert } from 'react-native';
3+
import { Button, TextInput, Appbar, Title } from 'react-native-paper';
4+
import { AuthContext } from '../context/AuthContext';
5+
import { updateUser } from '../api/auth';
6+
7+
const EditProfileScreen = ({ navigation }) => {
8+
const { user, token, updateUserInContext } = useContext(AuthContext);
9+
const [name, setName] = useState(user?.name || '');
10+
const [isSubmitting, setIsSubmitting] = useState(false);
11+
12+
const handleUpdateProfile = async () => {
13+
if (!name) {
14+
Alert.alert('Error', 'Name cannot be empty.');
15+
return;
16+
}
17+
setIsSubmitting(true);
18+
try {
19+
const response = await updateUser(token, { name });
20+
updateUserInContext(response.data);
21+
Alert.alert('Success', 'Profile updated successfully.');
22+
navigation.goBack();
23+
} catch (error) {
24+
console.error('Failed to update profile:', error);
25+
Alert.alert('Error', 'Failed to update profile.');
26+
} finally {
27+
setIsSubmitting(false);
28+
}
29+
};
30+
31+
return (
32+
<View style={styles.container}>
33+
<Appbar.Header>
34+
<Appbar.BackAction onPress={() => navigation.goBack()} />
35+
<Appbar.Content title="Edit Profile" />
36+
</Appbar.Header>
37+
<View style={styles.content}>
38+
<Title>Edit Your Details</Title>
39+
<TextInput
40+
label="Name"
41+
value={name}
42+
onChangeText={setName}
43+
style={styles.input}
44+
/>
45+
<Button
46+
mode="contained"
47+
onPress={handleUpdateProfile}
48+
loading={isSubmitting}
49+
disabled={isSubmitting}
50+
style={styles.button}
51+
>
52+
Save Changes
53+
</Button>
54+
</View>
55+
</View>
56+
);
57+
};
58+
59+
const styles = StyleSheet.create({
60+
container: {
61+
flex: 1,
62+
},
63+
content: {
64+
padding: 16,
65+
},
66+
input: {
67+
marginBottom: 16,
68+
},
69+
button: {
70+
marginTop: 8,
71+
},
72+
});
73+
74+
export default EditProfileScreen;

0 commit comments

Comments
 (0)