eletrotupi / tcc/ commit / 6e7ecd3

frontend: add a settings tab and do some light linting

Pedro Lucas Porcellis porcellis@eletrotupi.com · 6 months ago 6e7ecd390ce119d438ab5b3ab16fa1d9edeb434a Browse files
Parents 5d3a948
Changed 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
}