eletrotupi / tcc/ frontend/app/auth/reset-password.tsxaa62de4d0367338178e7bf9acae302ce760c282a
4.8 KB | 184 lines Raw
1
import React, { useState } from 'react';
2
import {
3
  View,
4
  Text,
5
  StyleSheet,
6
  ScrollView,
7
  KeyboardAvoidingView,
8
  Platform,
9
  Alert,
10
} from 'react-native';
11
import { Link, useLocalSearchParams, router } from 'expo-router';
12
import { SafeAreaView } from 'react-native-safe-area-context';
13
import { useThemeColor } from '@/hooks/use-theme-color';
14
import { Button, Input } from '@/components/ui';
15
import { useAuth } from '@/context/AuthContext';
16

17
export default function ResetPasswordScreen() {
18
  const { token } = useLocalSearchParams<{ token: string }>();
19
  const [password, setPassword] = useState('');
20
  const [confirmPassword, setConfirmPassword] = useState('');
21
  const [errors, setErrors] = useState<{
22
    password?: string;
23
    confirmPassword?: string;
24
  }>({});
25

26
  const { resetPassword } = useAuth();
27
  const [loading, setLoading] = useState(false);
28
  const textColor = useThemeColor({}, 'text');
29
  const backgroundColor = useThemeColor({}, 'background');
30
  const tintColor = useThemeColor({}, 'tint');
31

32
  const validateForm = () => {
33
    const newErrors: typeof errors = {};
34

35
    if (!password) {
36
      newErrors.password = 'A senha é obrigatória';
37
    } else if (password.length < 6) {
38
      newErrors.password = 'A senha deve conter pelo menos 6 caracteres';
39
    }
40

41
    if (!confirmPassword) {
42
      newErrors.confirmPassword = 'Por favor confirme sua senha';
43
    } else if (password !== confirmPassword) {
44
      newErrors.confirmPassword = 'As senhas não coincidem';
45
    }
46

47
    setErrors(newErrors);
48
    return Object.keys(newErrors).length === 0;
49
  };
50

51
  const handleResetPassword = async () => {
52
    if (!validateForm()) return;
53

54
    if (!token) {
55
      Alert.alert('Erro: ', 'Token de reset não encontrado. Por favor, solicite um novo link de recuperação.');
56
      return;
57
    }
58

59
    setLoading(true);
60
    try {
61
      await resetPassword(token, password);
62
      Alert.alert('Sucesso!', 'Senha recuperada com sucesso', [
63
        {
64
          text: 'OK',
65
          onPress: () => router.replace('/auth/login'),
66
        },
67
      ]);
68
    } catch (error: any) {
69
      Alert.alert('Erro: ', error.message || 'Falha em recuperar a conta');
70
    } finally {
71
      setLoading(false);
72
    }
73
  };
74

75
  return (
76
    <SafeAreaView style={[styles.container, { backgroundColor }]}>
77
      <KeyboardAvoidingView
78
        behavior='height'
79
        style={styles.keyboardView}
80
      >
81
        <ScrollView
82
          contentContainerStyle={styles.scrollContainer}
83
          showsVerticalScrollIndicator={false}
84
        >
85
          <View style={styles.header}>
86
            <Text style={[styles.title, { color: textColor }]}>Recuperar a conta</Text>
87
            <Text style={[styles.subtitle, { color: textColor, opacity: 0.7 }]}>
88
              Digite uma nova senha para sua conta
89
            </Text>
90
          </View>
91

92
          <View style={styles.form}>
93
            <Input
94
              label="Nova senha"
95
              type="password"
96
              value={password}
97
              onChangeText={setPassword}
98
              placeholder="Digite uma nova senha"
99
              error={errors.password}
100
              showPasswordToggle
101
            />
102

103
            <Input
104
              label="Confirmar nova senha"
105
              type="password"
106
              value={confirmPassword}
107
              onChangeText={setConfirmPassword}
108
              placeholder="Confirme a nova senha"
109
              error={errors.confirmPassword}
110
              showPasswordToggle
111
            />
112

113
            <Button
114
              title="Trocar senha"
115
              onPress={handleResetPassword}
116
              loading={loading}
117
              style={styles.resetButton}
118
            />
119
          </View>
120

121
          <View style={styles.footer}>
122
            <Text style={[styles.footerText, { color: textColor, opacity: 0.7 }]}>
123
              Lembrou da senha?{' '}
124
            </Text>
125
            <Link href="/auth/login" asChild style={[styles.link, { color: tintColor }]}>
126
              <Text style={[styles.link, { color: tintColor }]}>
127
                Faça login
128
              </Text>
129
            </Link>
130
          </View>
131
        </ScrollView>
132
      </KeyboardAvoidingView>
133
    </SafeAreaView>
134
  );
135
}
136

137
const styles = StyleSheet.create({
138
  container: {
139
    flex: 1,
140
  },
141
  keyboardView: {
142
    flex: 1,
143
  },
144
  scrollContainer: {
145
    flexGrow: 1,
146
    paddingHorizontal: 24,
147
    justifyContent: 'center',
148
    minHeight: '100%',
149
  },
150
  header: {
151
    alignItems: 'center',
152
    marginBottom: 40,
153
  },
154
  title: {
155
    fontSize: 28,
156
    fontWeight: 'bold',
157
    marginBottom: 8,
158
  },
159
  subtitle: {
160
    fontSize: 16,
161
    textAlign: 'center',
162
  },
163
  form: {
164
    marginBottom: 32,
165
  },
166
  resetButton: {
167
    marginTop: 8,
168
  },
169
  link: {
170
    textAlign: 'center',
171
    fontSize: 14,
172
    fontWeight: '500',
173
  },
174
  footer: {
175
    flexDirection: 'row',
176
    justifyContent: 'center',
177
    alignItems: 'center',
178
    marginTop: 'auto',
179
    paddingBottom: 20,
180
  },
181
  footerText: {
182
    fontSize: 14,
183
  },
184
});