eletrotupi / tcc/ frontend/app/profile.tsx17dd47ad86ed5f8c9bc9360a4eb3917a7a635c8d
6.7 KB | 274 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

44
    console.log("User@profile", user);
45
  }, [user])
46

47
  const backgroundColor = useThemeColor({}, 'background');
48
  const textColor = useThemeColor({}, 'text');
49

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

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

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

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

76
    setErrors(newErrors);
77

78
    return Object.keys(newErrors).length === 0;
79
  }
80

81
  const handleUpdate = async () => {
82
    if (!validateForm()) return;
83

84
    const data = {};
85

86
    data.firstName = firstName
87
    data.lastName = lastName
88
    data.email = email
89

90
    if (password) {
91
      data.password = password
92
    }
93

94
    try {
95
      const id = user.id;
96

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

105
      updateAuthUser(response.user);
106

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

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

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

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

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

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

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

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

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

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

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

214
        </ScrollView>
215
      </KeyboardAvoidingView>
216
    </SafeAreaView>
217
  )
218
}
219

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