eletrotupi / tcc/ frontend/app/profile.tsx7e3a6c43c649301ac62de0f61a1cd8449131c52c
6.7 KB | 272 lines Raw
1
import { useState, useEffect } from 'react';
2
import {
3
  View,
4
  Text,
5
  StyleSheet,
6
  ScrollView,
7
  KeyboardAvoidingView,
8
  Platform,
9
  Alert,
10
} from 'react-native';
11

12
import { ThemedView } from '@/components/ui/themed-view'
13
import { ThemedText } from '@/components/ui/themed-text'
14
import { Link, useLocalSearchParams, router } from 'expo-router';
15
import { StatusBar } from 'expo-status-bar';
16
import { SafeAreaView } from 'react-native-safe-area-context';
17
import { useThemeColor } from '@/hooks/use-theme-color';
18
import { Button, Input } from '@/components/ui';
19
import { useAuth } from '@/context/AuthContext';
20
import { apiClient } from '@/lib/api'
21
import { Card } from '@/components/ui/Cards';
22
import AvatarUpload  from '@/components/ui/AvatarUpload';
23
import { Typography, Spacing, Colors } from '@/constants/theme';
24

25
export default function Profile() {
26
  const { user, updateAuthUser } = useAuth();
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);
33
  const [errors, setErrors] = useState<{
34
    firstName?: string;
35
    password?: string;
36
    confirmPassword?: string;
37
  }>({});
38

39
  useEffect(() => {
40
    setFirstName(user.firstName)
41
    setLastName(user.lastName)
42
    setEmail(user.email)
43
  }, [user])
44

45
  const backgroundColor = useThemeColor({}, 'background');
46
  const textColor = useThemeColor({}, 'text');
47

48
  const validateForm = () => {
49
    const newErrors: {
50
      firstName?: string;
51
      email?: string;
52
      password?: string;
53
      confirmPassword?: string
54
    } = {};
55

56
    if (password) {
57
      if (!confirmPassword) {
58
        newErrors.confirmPassword = 'Precisa confirmar a senha';
59
      } else {
60
        if (password !== confirmPassword) {
61
          newErrors.confirmPassword = "Senhas não conferem";
62
        }
63
      }
64
    }
65

66
    if (!/\S+@\S+\.\S+/.test(email)) {
67
      newErrors.email = 'Por favor, use um email válido';
68
    }
69

70
    if (!firstName) {
71
      newErrors.firstName = 'É necessário ter um nome';
72
    }
73

74
    setErrors(newErrors);
75

76
    return Object.keys(newErrors).length === 0;
77
  }
78

79
  const handleUpdate = async () => {
80
    if (!validateForm()) return;
81

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
    try {
93
      const id = user.id;
94

95
      const response = await apiClient.updateUser({
96
        id,
97
        firstName,
98
        lastName,
99
        email,
100
        password
101
      });
102

103
      updateAuthUser(response.user);
104

105
      router.replace('/(tabs)/insights');
106
    } catch (error: any) {
107
      console.error("[PROFILE]", error)
108
      Alert.alert('Erro: ', 'Falha ao tentar atualizar o usuário');
109
    }
110
  }
111

112
  const onChangeAvatar = (userData) => {
113
    const { id, avatarKey, avatarURL, firstName, lastName, email } = userData;
114

115
    updateAuthUser({
116
      id,
117
      avatarKey,
118
      avatarURL,
119
      firstName,
120
      lastName,
121
      email
122
    });
123
  }
124

125
  return (
126
    <SafeAreaView style={[styles.container, { backgroundColor }]}>
127
      <StatusBar style={'dark'} />
128
      <KeyboardAvoidingView
129
        behavior='height'
130
        style={styles.keyboardView}
131
      >
132
        <ScrollView
133
          contentContainerStyle={styles.scrollContainer}
134
          showsVerticalScrollIndicator={false}
135
        >
136
          <AvatarUpload
137
            currentAvatar={user.avatarURL}
138
            onUploadSuccess={onChangeAvatar}
139
            onRemoveSuccess={onChangeAvatar} />
140

141
          <View style={styles.form}>
142
            <Card style={styles.cardBlock}>
143
              <Input
144
                label="Primeiro Nome"
145
                type="text"
146
                value={firstName}
147
                onChangeText={setFirstName}
148
                placeholder="Qual seu nome?"
149
                variant="darkGhost"
150
                error={errors.firstName}
151
              />
152

153
              <Input
154
                label="Sobrenome"
155
                type="text"
156
                value={lastName}
157
                variant="darkGhost"
158
                onChangeText={setLastName}
159
                placeholder="Qual seu sobrenome?"
160
                error={errors.lastName}
161
              />
162
            </Card>
163

164
            <Card style={styles.cardBlock}>
165
              <Input
166
                label="Email"
167
                type="text"
168
                value={email}
169
                variant="darkGhost"
170
                onChangeText={setEmail}
171
                placeholder="Qual seu email?"
172
                error={errors.email}
173
              />
174
            </Card>
175

176
            <Card style={styles.cardBlock}>
177
              <Input
178
                label="Nova senha"
179
                type="password"
180
                value={password}
181
                onChangeText={setPassword}
182
                placeholder="Digite uma nova senha"
183
                error={errors.password}
184
                variant="darkGhost"
185
                showPasswordToggle
186
              />
187

188
              <Input
189
                label="Confirmar nova senha"
190
                type="password"
191
                value={confirmPassword}
192
                onChangeText={setConfirmPassword}
193
                placeholder="Confirme a nova senha"
194
                error={errors.confirmPassword}
195
                variant="darkGhost"
196
                showPasswordToggle
197
              />
198

199
              <Text style={styles.cardBlockHint}>
200
                Preencha apenas se quiser mudar a sua senha
201
              </Text>
202
            </Card>
203

204
            <Button
205
              title="Atualizar perfil"
206
              onPress={handleUpdate}
207
              loading={loading}
208
              style={styles.resetButton}
209
            />
210
          </View>
211

212
        </ScrollView>
213
      </KeyboardAvoidingView>
214
    </SafeAreaView>
215
  )
216
}
217

218
const styles = StyleSheet.create({
219
  container: {
220
    flex: 1,
221
  },
222
  keyboardView: {
223
    flex: 1,
224
  },
225
  scrollContainer: {
226
    flexGrow: 1,
227
    paddingHorizontal: 24,
228
    justifyContent: 'start',
229
    minHeight: '100%',
230
  },
231
  header: {
232
    alignItems: 'left',
233
    marginBottom: 40,
234
  },
235
  title: {
236
    fontSize: 28,
237
    fontWeight: 'bold',
238
    marginBottom: 8,
239
  },
240
  subtitle: {
241
    fontSize: 16,
242
    textAlign: 'left',
243
  },
244
  form: {
245
    marginBottom: 32,
246
  },
247
  resetButton: {
248
    marginTop: 8,
249
  },
250
  link: {
251
    textAlign: 'center',
252
    fontSize: 14,
253
    fontWeight: '500',
254
  },
255
  footer: {
256
    flexDirection: 'row',
257
    justifyContent: 'center',
258
    alignItems: 'center',
259
    marginTop: 'auto',
260
    paddingBottom: 20,
261
  },
262
  footerText: {
263
    fontSize: 14,
264
  },
265
  cardBlock: {
266
    padding: Spacing.cardGap
267
  },
268
  cardBlockHint: {
269
    ...Typography.cardHint,
270
    color: Colors.light.textSecondary
271
  }
272
});