frontend: add a settings tab and do some light linting
Pedro Lucas Porcellis porcellis@eletrotupi.com · 6 months ago
6e7ecd390ce119d438ab5b3ab16fa1d9edeb434a Browse filesParents
5d3a948Changed files
4
Additions
+67
Deletions
-5
frontend/app/(tabs)/_layout.tsx
1 1
import { Tabs, Redirect, router } from 'expo-router';
2 2
import React, { useEffect } from 'react';
3 3
import { View, ActivityIndicator } from 'react-native';
4 4
5 5
import { HapticTab } from '@/components/misc/haptic-tab';
35 35
screenOptions={{
36 36
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
37 37
headerShown: false,
38 38
tabBarButton: HapticTab,
39 39
}}>
40 +
40 41
<Tabs.Screen
41 42
name="index"
42 43
options={{
43 44
title: 'Home',
44 45
tabBarIcon: ({ color }) => <IconSymbol size={28} name="house.fill" color={color} />,
45 46
}}
46 47
/>
48 +
47 49
<Tabs.Screen
48 50
name="explore"
49 51
options={{
50 52
title: 'Explore',
51 53
tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />,
54 +
}}
55 +
/>
56 +
57 +
<Tabs.Screen
58 +
name="settings"
59 +
options={{
60 +
title: 'Configurações',
61 +
tabBarIcon: ({ color }) => <IconSymbol size={28} name="settings.fill" color={color} />,
52 62
}}
53 63
/>
54 64
</Tabs>
55 65
);
56 66
}
/dev/null → frontend/app/(tabs)/settings.tsx
1 +
import { StyleSheet } from 'react-native';
2 +
import ParallaxScrollView from '@/components/misc/parallax-scroll-view';
3 +
4 +
import { ThemedText } from '@/components/misc/themed-text';
5 +
import { ThemedView } from '@/components/misc/themed-view';
6 +
import { IconSymbol } from '@/components/ui/icon-symbol';
7 +
import { Fonts } from '@/constants/theme';
8 +
9 +
export default function Settings() {
10 +
return (
11 +
<ParallaxScrollView
12 +
headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }}
13 +
headerImage={
14 +
<IconSymbol
15 +
size={310}
16 +
color="#808080"
17 +
name="chevron.left.forwardslash.chevron.right"
18 +
style={styles.headerImage}
19 +
/>
20 +
}>
21 +
<ThemedView style={styles.titleContainer}>
22 +
<ThemedText
23 +
type="title"
24 +
style={{
25 +
fontFamily: Fonts.rounded,
26 +
}}>
27 +
Explore
28 +
</ThemedText>
29 +
</ThemedView>
30 +
<ThemedText>
31 +
This app includes example code to help you get started.
32 +
</ThemedText>
33 +
</ParallaxScrollView>
34 +
)
35 +
}
36 +
37 +
38 +
const styles = StyleSheet.create({
39 +
headerImage: {
40 +
color: '#808080',
41 +
bottom: -90,
42 +
left: -35,
43 +
position: 'absolute',
44 +
},
45 +
titleContainer: {
46 +
flexDirection: 'row',
47 +
gap: 8,
48 +
},
49 +
});
frontend/components/ui/icon-symbol.tsx
1 1
// Fallback for using MaterialIcons on Android and web.
2 2
3 3
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
4 4
import { SymbolWeight, SymbolViewProps } from 'expo-symbols';
5 5
import { ComponentProps } from 'react';
16 16
const MAPPING = {
17 17
'house.fill': 'home',
18 18
'paperplane.fill': 'send',
19 19
'chevron.left.forwardslash.chevron.right': 'code',
20 20
'chevron.right': 'chevron-right',
21 +
'settings.fill': 'settings'
21 22
} as IconMapping;
22 23
23 24
/**
24 25
* An icon component that uses native SF Symbols on iOS, and Material Icons on Android and web.
25 26
* This ensures a consistent look across platforms, and optimal resource usage.
37 38
style?: StyleProp<TextStyle>;
38 39
weight?: SymbolWeight;
39 40
}) {
40 41
return <MaterialIcons color={color} size={size} name={MAPPING[name]} style={style} />;
41 42
}
frontend/context/AuthContext.tsx
1 1
import React, { createContext, useContext, useEffect, useState } from 'react';
2 2
import { apiClient, User } from '@/lib/api';
3 3
4 +
interface AuthProviderProps {
5 +
children: React.ReactNode;
6 +
}
7 +
4 8
interface AuthContextType {
5 9
user: User | null;
6 10
isLoading: boolean;
7 11
isAuthenticated: boolean;
8 12
login: (email: string, password: string) => Promise<void>;
22 26
export function useAuth() {
23 27
const context = useContext(AuthContext);
24 28
if (!context) {
25 29
throw new Error('useAuth must be used within an AuthProvider');
26 30
}
31 +
27 32
return context;
28 33
}
29 34
30 -
interface AuthProviderProps {
31 -
children: React.ReactNode;
32 -
}
33 -
34 -
export function AuthProvider({ children }: AuthProviderProps) {
35 +
export const AuthProvider = ({ children }: AuthProviderProps) => {
35 36
const [user, setUser] = useState<User | null>(null);
36 37
const [isLoading, setIsLoading] = useState(true);
37 38
38 39
const isAuthenticated = !!user;
39 40
68 69
}
69 70
};
70 71
71 72
const login = async (email: string, password: string) => {
72 73
setIsLoading(true);
74 +
73 75
try {
74 76
const response = await apiClient.login(email, password);
75 77
setUser(response.user);
76 78
} finally {
77 79
setIsLoading(false);
126 128
<AuthContext.Provider value={value}>
127 129
{children}
128 130
</AuthContext.Provider>
129 131
);
130 132
}