frontend: rework settings page
Parents:
de5e5ec1 file(s) changed
- frontend/app/(tabs)/settings.tsx +279 -99
frontend/app/(tabs)/settings.tsx
1 -
import { TouchableOpacity, StyleSheet, Text, SectionList, View, Alert } from 'react-native';
2 -
import { SafeAreaView, SafeAreaProvider } from 'react-native-safe-area-context';
3 -
import { useState } from 'react';
4 -
import ParallaxScrollView from '@/components/misc/parallax-scroll-view';
5 -
import { Link } from 'expo-router'
6 -
import { StatusBar } from 'expo-status-bar';
1 +
import {
2 +
TouchableOpacity,
3 +
StyleSheet,
4 +
Text,
5 +
SectionList,
6 +
View,
7 +
Alert,
8 +
Switch,
9 +
Pressable,
10 +
} from "react-native";
11 +
import { useState } from "react";
12 +
import { router } from "expo-router";
13 +
import { Card } from "@/components/ui/Cards";
14 +
import ScreenLayout from "@/components/ui/ScreenLayout";
15 +
import { BorderRadius, Colors, Fonts, Spacing } from "@/constants/theme";
16 +
import { useThemeColor } from "@/hooks/use-theme-color";
17 +
import { useAuth } from "@/context/AuthContext";
18 +
import { Section, SectionHeader } from "@/components/ui/Sections";
19 +
import { Ionicons, MaterialIcons } from "@expo/vector-icons";
20 +
import { Button } from "@/components/ui/Button";
7 21
8 -
import { ThemedText } from '@/components/misc/themed-text';
9 -
import { ThemedView } from '@/components/misc/themed-view';
10 -
import { IconSymbol } from '@/components/ui/icon-symbol';
11 -
import { Fonts } from '@/constants/theme';
12 -
import { useThemeColor } from '@/hooks/use-theme-color';
13 -
import { useAuth } from '@/context/AuthContext';
22 +
export default function Settings() {
23 +
const { user, logout } = useAuth();
24 +
const [allowNotifications, setAllowNotifications] = useState(false);
25 +
const [allowWeeklyInsights, setAllowWeeklyInsights] = useState(false);
14 26
15 -
const SECTIONS = [
16 -
{
17 -
title: 'Geral',
18 -
data: [{
19 -
title: 'Perfil & Senha',
20 -
path: '/profile'
21 -
}]
22 -
},
23 -
{
24 -
title: 'Sobre',
25 -
data: [
27 +
const textColor = useThemeColor({}, "text");
28 +
29 +
const onNotificationPress = () => {};
30 +
31 +
const handleLogout = async () => {
32 +
Alert.alert("Sair", "Tem certeza que quer sair?", [
33 +
{ text: "Cancelar", style: "cancel" },
26 34
{
27 -
title: 'Sobre o aplicativo',
28 -
path: '/about'
29 -
},
30 -
{
31 -
title: 'O que acontece com seus dados?',
32 -
path: '/data'
35 +
text: "Sair",
36 +
style: "destructive",
37 +
onPress: logout,
33 38
},
34 -
{
35 -
title: 'Sair',
36 -
path: '/logout',
37 -
logout: true
38 -
}
39 -
]
40 -
}
41 -
]
39 +
]);
40 +
};
42 41
43 -
export default function Settings() {
44 -
const { user, logout } = useAuth();
45 -
const [options] = useState([
46 -
{ id: 'profile', name: 'Perfil', path: '/profile'}
47 -
])
42 +
const handleProfilePress = () => {
43 +
router.push("/profile");
44 +
};
48 45
49 -
const textColor = useThemeColor({}, 'text');
50 -
const tintColor = useThemeColor({}, 'tint');
46 +
const handleInvisibleMode = () => {};
51 47
52 -
const handleLogout = async () => {
53 -
Alert.alert(
54 -
'Sair',
55 -
'Tem certeza que quer sair?',
56 -
[
57 -
{ text: 'Cancelar', style: 'cancel' },
58 -
{
59 -
text: 'Sair',
60 -
style: 'destructive',
61 -
onPress: logout
48 +
const handleDataExport = () => {
49 +
Alert.alert("Exportar dados", "Deseja exportar seus dados?", [
50 +
{ text: "Cancelar", style: "cancel" },
51 +
{
52 +
text: "Exportar",
53 +
style: "destructive",
54 +
onPress: () => {
55 +
Alert.alert(
56 +
"Exportar dados",
57 +
"Você receberá um e-mail com os dados exportados.",
58 +
[{ text: "OK", style: "default" }],
59 +
);
62 60
},
63 -
]
64 -
);
61 +
},
62 +
]);
65 63
};
66 64
67 -
const renderItem = ({item}) => {
68 -
const itemStyle = [
69 -
styles.item,
70 -
]
65 +
return (
66 +
<ScreenLayout
67 +
userName={user.firstName}
68 +
userAvatar={user.avatarURL}
69 +
onNotificationPress={onNotificationPress}
70 +
showNotificationBadge={true}
71 +
>
72 +
<Section>
73 +
<SectionHeader title="Perfil" />
71 74
72 -
const itemColor = { color: item.logout ? '#FF2C2C' : textColor }
75 +
<Card style={{ padding: Spacing.cardGap }} onPress={handleProfilePress}>
76 +
<View
77 +
style={{
78 +
flexDirection: "row",
79 +
alignItems: "center",
80 +
justifyContent: "space-between",
81 +
}}
82 +
>
83 +
<View
84 +
style={{
85 +
flexDirection: "column",
86 +
alignItems: "center",
87 +
justifyContent: "space-between",
88 +
}}
89 +
>
90 +
<Text style={styles.cardTitle}>Dados Pessoais</Text>
91 +
<Text style={styles.cardSubtitle}>Nome, Email e senha</Text>
92 +
</View>
73 93
74 -
if (item.logout) {
75 -
return (
76 -
<TouchableOpacity onPress={handleLogout} style={itemStyle}>
77 -
<Text style={itemColor}>
78 -
Sair
79 -
</Text>
80 -
</TouchableOpacity>
81 -
)
82 -
}
94 +
<Ionicons name="chevron-forward" size={24} color={textColor} />
95 +
</View>
96 +
</Card>
97 +
</Section>
98 +
99 +
<Section>
100 +
<SectionHeader title="Notificações" />
101 +
102 +
<Card style={{ padding: Spacing.cardGap }}>
103 +
<View
104 +
style={{
105 +
flexDirection: "row",
106 +
alignItems: "center",
107 +
justifyContent: "space-between",
108 +
}}
109 +
>
110 +
<View
111 +
style={[
112 +
styles.cardIcon,
113 +
{ backgroundColor: Colors.light.accentBlue },
114 +
]}
115 +
>
116 +
<Ionicons
117 +
name="notifications-outline"
118 +
size={20}
119 +
color={Colors.light.black}
120 +
/>
121 +
</View>
83 122
84 -
return (
85 -
<View>
86 -
<Link key={item.id} href={item.path} asChild style={itemStyle}>
87 -
<TouchableOpacity>
88 -
<Text style={itemColor}>
89 -
{item.title}
90 -
</Text>
123 +
<View
124 +
style={{
125 +
flexDirection: "column",
126 +
alignItems: "flex-start",
127 +
justifyContent: "space-between",
128 +
marginLeft: 12,
129 +
flex: 1,
130 +
}}
131 +
>
132 +
<Text style={styles.cardTitle}>Notificações</Text>
133 +
<Text>Diário as 20:00</Text>
134 +
</View>
135 +
136 +
<Switch
137 +
onValueChange={setAllowNotifications}
138 +
thumbColor={Colors.light.tint}
139 +
trackColor={{
140 +
false: Colors.light.disabled,
141 +
true: Colors.light.gray,
142 +
}}
143 +
value={allowNotifications}
144 +
/>
145 +
</View>
146 +
147 +
<View style={styles.divider} />
148 +
149 +
<View
150 +
style={{
151 +
flexDirection: "row",
152 +
alignItems: "center",
153 +
justifyContent: "space-between",
154 +
}}
155 +
>
156 +
<View
157 +
style={[
158 +
styles.cardIcon,
159 +
{ backgroundColor: Colors.light.accentPurple },
160 +
]}
161 +
>
162 +
<Ionicons name="sparkles" size={20} color={Colors.light.black} />
163 +
</View>
164 +
165 +
<View
166 +
style={{
167 +
flexDirection: "column",
168 +
alignItems: "flex-start",
169 +
justifyContent: "space-between",
170 +
marginLeft: 12,
171 +
flex: 1,
172 +
}}
173 +
>
174 +
<Text style={styles.cardTitle}>Indicadores semanais</Text>
175 +
<Text>Relatórios de progressos</Text>
176 +
</View>
177 +
178 +
<Switch
179 +
onValueChange={setAllowWeeklyInsights}
180 +
value={allowWeeklyInsights}
181 +
thumbColor={Colors.light.tint}
182 +
trackColor={{
183 +
false: Colors.light.disabled,
184 +
true: Colors.light.gray,
185 +
}}
186 +
/>
187 +
</View>
188 +
</Card>
189 +
</Section>
190 +
191 +
<Section>
192 +
<SectionHeader title="Privacidade" />
193 +
194 +
<Card style={{ padding: Spacing.cardGap }}>
195 +
<TouchableOpacity
196 +
style={{
197 +
flexDirection: "row",
198 +
alignItems: "center",
199 +
justifyContent: "space-between",
200 +
}}
201 +
onPress={handleInvisibleMode}
202 +
>
203 +
<View style={{ flexDirection: "row", alignItems: "center" }}>
204 +
<MaterialIcons
205 +
name="lock"
206 +
size={24}
207 +
color={Colors.light.textSecondary}
208 +
/>
209 +
210 +
<Text
211 +
style={{
212 +
marginLeft: 8,
213 +
color: Colors.light.text,
214 +
fontSize: 14,
215 +
fontWeight: "500" as const,
216 +
}}
217 +
>
218 +
Modo Invisível
219 +
</Text>
220 +
</View>
221 +
222 +
<Ionicons name="chevron-forward" size={24} color={textColor} />
91 223
</TouchableOpacity>
92 -
</Link>
93 -
</View>
94 -
)
95 -
}
96 224
97 -
return (
98 -
<SafeAreaProvider>
99 -
<SafeAreaView style={styles.container} edges={['top']}>
100 -
<StatusBar style="dark" />
101 -
<SectionList
102 -
sections={SECTIONS}
103 -
keyExtractor={(item, index) => item.title + index}
104 -
renderItem={renderItem}
105 -
renderSectionHeader={({section: {title}}) => (
106 -
<ThemedText style={styles.header}>{title}</ThemedText>
107 -
)} />
108 -
</SafeAreaView>
109 -
</SafeAreaProvider>
110 -
)
225 +
<View style={styles.divider} />
226 +
227 +
<TouchableOpacity
228 +
style={{
229 +
flexDirection: "row",
230 +
alignItems: "center",
231 +
justifyContent: "space-between",
232 +
}}
233 +
onPress={handleDataExport}
234 +
>
235 +
<View style={{ flexDirection: "row", alignItems: "center" }}>
236 +
<MaterialIcons
237 +
name="storage"
238 +
size={24}
239 +
color={Colors.light.textSecondary}
240 +
/>
241 +
242 +
<Text
243 +
style={{
244 +
marginLeft: 8,
245 +
color: Colors.light.text,
246 +
fontSize: 14,
247 +
fontWeight: "500" as const,
248 +
}}
249 +
>
250 +
Exportar Meus Dados
251 +
</Text>
252 +
</View>
253 +
254 +
<MaterialIcons
255 +
name="file-download"
256 +
size={24}
257 +
color={Colors.light.textSecondary}
258 +
/>
259 +
</TouchableOpacity>
260 +
</Card>
261 +
</Section>
262 +
263 +
<Button
264 +
title="Sair da Conta"
265 +
onPress={handleLogout}
266 +
variant="outline"
267 +
style={{ borderColor: Colors.light.danger }}
268 +
textStyle={{ color: Colors.light.danger }}
269 +
/>
270 +
</ScreenLayout>
271 +
);
111 272
}
112 273
113 274
const styles = StyleSheet.create({
114 275
container: {
115 276
flex: 1,
116 277
marginHorizontal: 16,
117 -
paddingTop: 10
278 +
paddingTop: 10,
118 279
},
119 280
item: {
120 281
paddingTop: 20,
121 282
paddingBottom: 20,
122 283
},
123 284
header: {
124 285
fontSize: 22,
125 -
fontWeight: 'bold'
286 +
fontWeight: "bold",
287 +
},
288 +
cardIcon: {
289 +
paddingVertical: 15,
290 +
paddingHorizontal: 14,
291 +
width: 48,
292 +
borderRadius: BorderRadius.md,
293 +
},
294 +
cardTitle: {
295 +
fontSize: 16,
296 +
fontWeight: "bold",
297 +
},
298 +
cardSubtitle: {
299 +
fontSize: 12,
300 +
color: Colors.light.textSecondary,
126 301
},
127 302
logout: {
128 -
textColor: '#FF2C2C'
129 -
}
303 +
color: "#FF2C2C",
304 +
},
305 +
divider: {
306 +
height: StyleSheet.hairlineWidth,
307 +
backgroundColor: "#D1D5DB",
308 +
marginVertical: 16,
309 +
},
130 310
});