frontend: guard nullable user reads
Pedro Lucas Porcellis porcellis@eletrotupi.com · 12 days ago
bee79a3ab499c11539d5799b6c9cb1fc0d8ba1e0 Browse filesParents
9897f03Changed files
7
Additions
+21
Deletions
-35
frontend/app/(tabs)/actions.tsx
1 1
import { View, StyleSheet } from "react-native";
2 2
import { Text } from "@/components/ui/Text";
3 3
import { ThemedView } from "@/components/misc/themed-view";
4 4
import { ScreenLayout } from "@/components/ui/ScreenLayout";
5 5
import { useAuth } from "@/context/AuthContext";
28 28
router.push("/triggers/new");
29 29
};
30 30
31 31
return (
32 32
<ScreenLayout
33 -
userName={user.firstName}
34 -
userAvatar={user.avatarURL}
33 +
userName={user?.firstName}
34 +
userAvatar={user?.avatarURL}
35 35
showNotificationBadge={true}
36 36
>
37 37
<Section>
38 38
<SectionHeader
39 39
title="Ações de Cuidado"
172 172
fontSize: 12,
173 173
lineHeight: 16,
174 174
alignItems: "center",
175 175
},
176 176
});
frontend/app/(tabs)/history.tsx
1 1
import { useState } from "react";
2 2
import { ScrollView, View } from "react-native";
3 3
import { ScreenLayout } from "@/components/ui/ScreenLayout";
4 4
import { Section, SectionHeader } from "@/components/ui/Sections";
5 5
import { FilterPills } from "@/components/ui/FilterPills";
43 43
);
44 44
const grouped = useHistoryFeed(activeFilter);
45 45
46 46
return (
47 47
<ScreenLayout
48 -
userName={user.firstName}
49 -
userAvatar={user.avatarURL}
48 +
userName={user?.firstName}
49 +
userAvatar={user?.avatarURL}
50 50
showNotificationBadge={true}
51 51
>
52 52
<ScrollView testID="history-list">
53 53
<FilterPills active={activeFilter} onChange={setActiveFilter} />
54 54
72 72
)}
73 73
</ScrollView>
74 74
</ScreenLayout>
75 75
);
76 76
}
frontend/app/(tabs)/insights.tsx
1 1
import { View, ScrollView, StyleSheet } from "react-native";
2 2
3 3
import { ThemedView } from "@/components/misc/themed-view";
4 4
import { ScreenLayout } from "@/components/ui/ScreenLayout";
5 5
import { useAuth } from "@/context/AuthContext";
16 16
export default function Insights() {
17 17
const { user } = useAuth();
18 18
19 19
return (
20 20
<ScreenLayout
21 -
userName={user.firstName}
22 -
userAvatar={user.avatarURL}
21 +
userName={user?.firstName}
22 +
userAvatar={user?.avatarURL}
23 23
showNotificationBadge={true}
24 24
>
25 25
<WeeklyResume
26 26
avgMood="Neutro"
27 27
stats={[
130 130
insightMetric: {
131 131
...Typography.headlineLg,
132 132
fontSize: 22,
133 133
},
134 134
});
frontend/app/(tabs)/new/index.tsx
1 1
import { useEffect, useState } from "react";
2 2
import { StyleSheet, View, ActivityIndicator } from "react-native";
3 3
4 4
import { Text } from "@/components/ui/Text";
5 5
import { ThemedView } from "@/components/misc/themed-view";
40 40
router.navigate(`/new/entry?initialMood=${mood}`);
41 41
};
42 42
43 43
return (
44 44
<ScreenLayout
45 -
userName={user.firstName}
46 -
userAvatar={user.avatarURL}
45 +
userName={user?.firstName}
46 +
userAvatar={user?.avatarURL}
47 47
showNotificationBadge={true}
48 48
>
49 49
<Section>
50 50
<SectionHeader
51 51
title="Como você está hoje?"
161 161
fontSize: 11,
162 162
fontWeight: 600,
163 163
lineHeight: 16.5,
164 164
},
165 165
});
frontend/app/(tabs)/settings.tsx
1 1
import {
2 2
TouchableOpacity,
3 3
StyleSheet,
4 4
SectionList,
5 5
View,
83 83
}
84 84
};
85 85
86 86
return (
87 87
<ScreenLayout
88 -
userName={user.firstName}
89 -
userAvatar={user.avatarURL}
88 +
userName={user?.firstName}
89 +
userAvatar={user?.avatarURL}
90 90
showNotificationBadge={true}
91 91
>
92 92
<Section>
93 93
<SectionHeader title="Perfil" />
94 94
371 371
height: StyleSheet.hairlineWidth,
372 372
backgroundColor: "#D1D5DB",
373 373
marginVertical: 16,
374 374
},
375 375
});
frontend/app/index.tsx
1 1
import { Redirect } from "expo-router";
2 2
import { useAuth } from "@/context/AuthContext";
3 3
import { ActivityIndicator, View } from "react-native";
4 4
5 5
export default function Index() {
13 13
</View>
14 14
);
15 15
}
16 16
17 17
if (isAuthenticated) {
18 -
if (user.active) {
18 +
if (user?.active) {
19 19
url = "/(tabs)/new";
20 20
} else {
21 21
url = "/auth/activate";
22 22
}
23 23
}
24 24
25 25
return <Redirect href={url} />;
26 26
}
frontend/app/profile.tsx
1 1
import { useState, useEffect } from 'react';
2 2
import {
3 3
View,
4 4
StyleSheet,
5 5
ScrollView,
22 22
import { Typography, Spacing, Colors } from '@/constants/theme';
23 23
24 24
export default function Profile() {
25 25
const { user, updateAuthUser } = useAuth();
26 26
const { showToast } = useToast();
27 -
const [firstName, setFirstName] = useState(user.firstName);
28 -
const [lastName, setLastName] = useState(user.lastName);
29 -
const [email, setEmail] = useState(user.email);
30 -
const [password, setPassword] = useState();
31 -
const [confirmPassword, setConfirmPassword] = useState();
32 -
const [loading, setLoading] = useState(false);
27 +
const [firstName, setFirstName] = useState(user?.firstName ?? '');
28 +
const [lastName, setLastName] = useState(user?.lastName ?? '');
29 +
const [email, setEmail] = useState(user?.email ?? '');
30 +
const [password, setPassword] = useState('');
31 +
const [confirmPassword, setConfirmPassword] = useState('');
32 +
const [loading] = useState(false);
33 33
const [errors, setErrors] = useState<{
34 34
firstName?: string;
35 +
lastName?: string;
36 +
email?: string;
35 37
password?: string;
36 38
confirmPassword?: string;
37 39
}>({});
38 40
39 -
useEffect(() => {
40 -
setFirstName(user.firstName)
41 -
setLastName(user.lastName)
42 -
setEmail(user.email)
43 -
}, [user])
44 -
45 41
const backgroundColor = useThemeColor({}, 'background');
46 -
const textColor = useThemeColor({}, 'text');
47 42
48 43
const validateForm = () => {
49 44
const newErrors: {
50 45
firstName?: string;
51 46
email?: string;
75 70
76 71
return Object.keys(newErrors).length === 0;
77 72
}
78 73
79 74
const handleUpdate = async () => {
75 +
if (!user) return;
80 76
if (!validateForm()) return;
81 77
82 -
const data = {};
83 -
84 -
data.firstName = firstName
85 -
data.lastName = lastName
86 -
data.email = email
87 -
88 -
if (password) {
89 -
data.password = password
90 -
}
91 -
92 78
try {
93 79
const id = user.id;
94 80
95 81
const response = await apiClient.updateUser({
96 82
id,
127 113
<ScrollView
128 114
contentContainerStyle={styles.scrollContainer}
129 115
showsVerticalScrollIndicator={false}
130 116
>
131 117
<AvatarUpload
132 -
currentAvatar={user.avatarURL}
118 +
currentAvatar={user?.avatarURL}
133 119
onUploadSuccess={onChangeAvatar}
134 120
onRemoveSuccess={onChangeAvatar} />
135 121
136 122
<View style={styles.form}>
137 123
<Card style={styles.cardBlock}>
263 249
cardBlockHint: {
264 250
...Typography.cardHint,
265 251
color: Colors.light.textSecondary
266 252
}
267 253
});