eletrotupi / tcc/ frontend/app/(tabs)/settings.tsx8537a60124ae506d0bd448606eb32f95edd465d9
10.0 KB | 365 lines Raw
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";
21
import { TimePicker } from "@/components/ui/TimePicker";
22
import { usePatchUserMe } from "@/hooks/useUserPreferences.queries";
23

24
export default function Settings() {
25
  const { user, logout, updateAuthUser } = useAuth();
26
  const [allowWeeklyInsights, setAllowWeeklyInsights] = useState(false);
27

28
  const notificationsEnabled = user?.notificationsEnabled ?? true;
29
  const dailyReminderTime = user?.dailyReminderTime ?? "20:00";
30

31
  const patchUserMe = usePatchUserMe((updatedUser) => {
32
    updateAuthUser(updatedUser);
33
  });
34

35
  const handleNotificationToggle = (value: boolean) => {
36
    patchUserMe.mutate({ notificationsEnabled: value });
37
  };
38

39
  const handleTimeChange = (date: Date) => {
40
    const time = `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
41
    patchUserMe.mutate({ dailyReminderTime: time });
42
  };
43

44
  const textColor = useThemeColor({}, "text");
45

46
  const handleLogout = async () => {
47
    Alert.alert("Sair", "Tem certeza que quer sair?", [
48
      { text: "Cancelar", style: "cancel" },
49
      {
50
        text: "Sair",
51
        style: "destructive",
52
        onPress: logout,
53
      },
54
    ]);
55
  };
56

57
  const handleProfilePress = () => {
58
    router.push("/profile");
59
  };
60

61
  const handleInvisibleMode = () => {};
62

63
  const handleDataExport = () => {
64
    Alert.alert("Exportar dados", "Deseja exportar seus dados?", [
65
      { text: "Cancelar", style: "cancel" },
66
      {
67
        text: "Exportar",
68
        style: "destructive",
69
        onPress: () => {
70
          Alert.alert(
71
            "Exportar dados",
72
            "Você receberá um e-mail com os dados exportados.",
73
            [{ text: "OK", style: "default" }],
74
          );
75
        },
76
      },
77
    ]);
78
  };
79

80
  return (
81
    <ScreenLayout
82
      userName={user.firstName}
83
      userAvatar={user.avatarURL}
84
      showNotificationBadge={true}
85
    >
86
      <Section>
87
        <SectionHeader title="Perfil" />
88

89
        <Card style={{ padding: Spacing.cardGap }} onPress={handleProfilePress}>
90
          <View
91
            style={{
92
              flexDirection: "row",
93
              alignItems: "center",
94
              justifyContent: "space-between",
95
            }}
96
          >
97
            <View
98
              style={{
99
                flexDirection: "column",
100
                alignItems: "center",
101
                justifyContent: "space-between",
102
              }}
103
            >
104
              <Text style={styles.cardTitle}>Dados Pessoais</Text>
105
              <Text style={styles.cardSubtitle}>Nome, Email e senha</Text>
106
            </View>
107

108
            <Ionicons name="chevron-forward" size={24} color={textColor} />
109
          </View>
110
        </Card>
111
      </Section>
112

113
      <Section>
114
        <SectionHeader title="Notificações" />
115

116
        <Card style={{ padding: Spacing.cardGap }}>
117
          <View
118
            style={{
119
              flexDirection: "row",
120
              alignItems: "center",
121
              justifyContent: "space-between",
122
            }}
123
          >
124
            <View
125
              style={[
126
                styles.cardIcon,
127
                { backgroundColor: Colors.light.accentBlue, marginBottom: 5 },
128
              ]}
129
            >
130
              <Ionicons
131
                name="notifications-outline"
132
                size={20}
133
                color={Colors.light.black}
134
              />
135
            </View>
136

137
            <View
138
              style={{
139
                flexDirection: "column",
140
                alignItems: "flex-start",
141
                justifyContent: "space-between",
142
                marginLeft: 12,
143
                flex: 1,
144
              }}
145
            >
146
              <Text style={styles.cardTitle}>Lembrete diário de humor</Text>
147
              <Text>{notificationsEnabled ? `Diário às ${dailyReminderTime}` : "Desativado"}</Text>
148
            </View>
149

150
            <Switch
151
              onValueChange={handleNotificationToggle}
152
              thumbColor={Colors.light.tint}
153
              trackColor={{
154
                false: Colors.light.disabled,
155
                true: Colors.light.gray,
156
              }}
157
              value={notificationsEnabled}
158
              disabled={patchUserMe.isPending}
159
            />
160
          </View>
161

162
          {notificationsEnabled && (
163
            <TimePicker
164
              value={(() => {
165
                const [h, m] = dailyReminderTime.split(":").map(Number);
166
                const d = new Date();
167
                d.setHours(h, m, 0, 0);
168
                return d;
169
              })()}
170
              onChange={handleTimeChange}
171
            />
172
          )}
173

174
          <View style={styles.divider} />
175

176
          <View
177
            style={{
178
              flexDirection: "row",
179
              alignItems: "center",
180
              justifyContent: "space-between",
181
            }}
182
          >
183
            <View
184
              style={[
185
                styles.cardIcon,
186
                { backgroundColor: Colors.light.accentPurple },
187
              ]}
188
            >
189
              <Ionicons name="sparkles" size={20} color={Colors.light.black} />
190
            </View>
191

192
            <View
193
              style={{
194
                flexDirection: "column",
195
                alignItems: "flex-start",
196
                justifyContent: "space-between",
197
                marginLeft: 12,
198
                flex: 1,
199
              }}
200
            >
201
              <Text style={styles.cardTitle}>Indicadores semanais</Text>
202
              <Text>Relatórios de progressos</Text>
203
            </View>
204

205
            <Switch
206
              onValueChange={setAllowWeeklyInsights}
207
              value={allowWeeklyInsights}
208
              thumbColor={Colors.light.tint}
209
              trackColor={{
210
                false: Colors.light.disabled,
211
                true: Colors.light.gray,
212
              }}
213
            />
214
          </View>
215
        </Card>
216
      </Section>
217

218
      <Section>
219
        <SectionHeader title="Relatório" />
220
        <Card
221
          style={{ padding: Spacing.cardGap }}
222
          onPress={() => router.push("/report")}
223
        >
224
          <View
225
            style={{
226
              flexDirection: "row",
227
              alignItems: "center",
228
              justifyContent: "space-between",
229
            }}
230
          >
231
            <View style={{ flexDirection: "row", alignItems: "center" }}>
232
              <MaterialIcons
233
                name="picture-as-pdf"
234
                size={24}
235
                color={Colors.light.textSecondary}
236
              />
237
              <Text style={{ marginLeft: 8, ...styles.cardTitle }}>
238
                Gerar Relatório
239
              </Text>
240
            </View>
241
            <Ionicons name="chevron-forward" size={24} color={textColor} />
242
          </View>
243
        </Card>
244
      </Section>
245

246
      <Section>
247
        <SectionHeader title="Privacidade" />
248

249
        <Card style={{ padding: Spacing.cardGap }}>
250
          <TouchableOpacity
251
            style={{
252
              flexDirection: "row",
253
              alignItems: "center",
254
              justifyContent: "space-between",
255
            }}
256
            onPress={handleInvisibleMode}
257
          >
258
            <View style={{ flexDirection: "row", alignItems: "center" }}>
259
              <MaterialIcons
260
                name="lock"
261
                size={24}
262
                color={Colors.light.textSecondary}
263
              />
264

265
              <Text
266
                style={{
267
                  marginLeft: 8,
268
                  color: Colors.light.text,
269
                  fontSize: 14,
270
                  fontWeight: "500" as const,
271
                }}
272
              >
273
                Privacidade
274
              </Text>
275
            </View>
276

277
            <Ionicons name="chevron-forward" size={24} color={textColor} />
278
          </TouchableOpacity>
279

280
          <View style={styles.divider} />
281

282
          <TouchableOpacity
283
            style={{
284
              flexDirection: "row",
285
              alignItems: "center",
286
              justifyContent: "space-between",
287
            }}
288
            onPress={handleDataExport}
289
          >
290
            <View style={{ flexDirection: "row", alignItems: "center" }}>
291
              <MaterialIcons
292
                name="storage"
293
                size={24}
294
                color={Colors.light.textSecondary}
295
              />
296

297
              <Text
298
                style={{
299
                  marginLeft: 8,
300
                  color: Colors.light.text,
301
                  fontSize: 14,
302
                  fontWeight: "500" as const,
303
                }}
304
              >
305
                Exportar Meus Dados
306
              </Text>
307
            </View>
308

309
            <MaterialIcons
310
              name="file-download"
311
              size={24}
312
              color={Colors.light.textSecondary}
313
            />
314
          </TouchableOpacity>
315
        </Card>
316
      </Section>
317

318
      <Button
319
        title="Sair da Conta"
320
        onPress={handleLogout}
321
        variant="outline"
322
        style={{ borderColor: Colors.light.danger }}
323
        textStyle={{ color: Colors.light.danger }}
324
      />
325
    </ScreenLayout>
326
  );
327
}
328

329
const styles = StyleSheet.create({
330
  container: {
331
    flex: 1,
332
    marginHorizontal: 16,
333
    paddingTop: 10,
334
  },
335
  item: {
336
    paddingTop: 20,
337
    paddingBottom: 20,
338
  },
339
  header: {
340
    fontSize: 22,
341
    fontWeight: "bold",
342
  },
343
  cardIcon: {
344
    paddingVertical: 15,
345
    paddingHorizontal: 14,
346
    width: 48,
347
    borderRadius: BorderRadius.md,
348
  },
349
  cardTitle: {
350
    fontSize: 16,
351
    fontWeight: "bold",
352
  },
353
  cardSubtitle: {
354
    fontSize: 12,
355
    color: Colors.light.textSecondary,
356
  },
357
  logout: {
358
    color: "#FF2C2C",
359
  },
360
  divider: {
361
    height: StyleSheet.hairlineWidth,
362
    backgroundColor: "#D1D5DB",
363
    marginVertical: 16,
364
  },
365
});