eletrotupi / tcc/ frontend/app/(tabs)/settings.tsx1495e32eb83d60fb8dd6a1c539de3fbefa9e19b1
10.0 KB | 363 lines Raw
1
import {
2
  TouchableOpacity,
3
  StyleSheet,
4
  SectionList,
5
  View,
6
  Alert,
7
  Switch,
8
  Pressable,
9
} from "react-native";
10
import { Text } from '@/components/ui/Text';
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
import { useToast } from '@/context/ToastContext';
24

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

30
  const notificationsEnabled = user?.notificationsEnabled ?? true;
31
  const dailyReminderTime = user?.dailyReminderTime ?? "20:00";
32

33
  const patchUserMe = usePatchUserMe((updatedUser) => {
34
    updateAuthUser(updatedUser);
35
  });
36

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

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

46
  const textColor = useThemeColor({}, "text");
47

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

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

63
  const handleInvisibleMode = () => {};
64

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

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

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

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

111
      <Section>
112
        <SectionHeader title="Notificações" />
113

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

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

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

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

172
          <View style={styles.divider} />
173

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

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

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

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

244
      <Section>
245
        <SectionHeader title="Privacidade" />
246

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

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

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

278
          <View style={styles.divider} />
279

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

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

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

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

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