eletrotupi / tcc/ frontend/app/auth/reset-password.tsxc901c35af9c84b6a29e5185545ced1129f33b8f4
3.8 KB | 135 lines Raw
1
import React, { useState } from 'react';
2
import { StyleSheet, View } from 'react-native';
3
import { Link, useLocalSearchParams, router } from 'expo-router';
4
import { useThemeColor } from '@/hooks/use-theme-color';
5
import { Button, Input } from '@/components/ui';
6
import { Text } from '@/components/ui/Text';
7
import { AuthScreen } from '@/components/auth/AuthScreen';
8
import { useAuth } from '@/context/AuthContext';
9
import { useToast } from '@/context/ToastContext';
10
import { translateError } from '@/lib/errors/translations';
11

12
export default function ResetPasswordScreen() {
13
  const { token } = useLocalSearchParams<{ token: string }>();
14
  const [password, setPassword] = useState('');
15
  const [confirmPassword, setConfirmPassword] = useState('');
16
  const [errors, setErrors] = useState<{
17
    password?: string;
18
    confirmPassword?: string;
19
  }>({});
20

21
  const { resetPassword } = useAuth();
22
  const { showToast } = useToast();
23
  const [loading, setLoading] = useState(false);
24
  const textColor = useThemeColor({}, 'text');
25
  const tintColor = useThemeColor({}, 'tint');
26

27
  const validateForm = () => {
28
    const newErrors: typeof errors = {};
29

30
    if (!password) {
31
      newErrors.password = 'A senha é obrigatória';
32
    } else if (password.length < 6) {
33
      newErrors.password = 'A senha deve conter pelo menos 6 caracteres';
34
    }
35

36
    if (!confirmPassword) {
37
      newErrors.confirmPassword = 'Por favor confirme sua senha';
38
    } else if (password !== confirmPassword) {
39
      newErrors.confirmPassword = 'As senhas não coincidem';
40
    }
41

42
    setErrors(newErrors);
43
    return Object.keys(newErrors).length === 0;
44
  };
45

46
  const handleResetPassword = async () => {
47
    if (!validateForm()) return;
48

49
    if (!token) {
50
      showToast('Token não encontrado. Solicite um novo link de recuperação.', 'error');
51
      return;
52
    }
53

54
    setLoading(true);
55
    try {
56
      await resetPassword(token, password);
57
      showToast('Senha recuperada com sucesso!', 'success');
58
      router.replace('/auth/login');
59
    } catch (error) {
60
      showToast(translateError(error) || 'Falha em recuperar a conta', 'error');
61
    } finally {
62
      setLoading(false);
63
    }
64
  };
65

66
  return (
67
    <AuthScreen
68
      title="Recuperar a conta"
69
      subtitle="Digite uma nova senha para sua conta"
70
      footer={
71
        <View style={styles.footer}>
72
          <Text style={[styles.footerText, { color: textColor, opacity: 0.7 }]}>
73
            Lembrou da senha?{' '}
74
          </Text>
75
          <Link href="/auth/login" asChild style={StyleSheet.flatten([styles.link, { color: tintColor }])}>
76
            <Text style={StyleSheet.flatten([styles.link, { color: tintColor }])}>
77
              Faça login
78
            </Text>
79
          </Link>
80
        </View>
81
      }
82
    >
83
      <View style={styles.form}>
84
        <Input
85
          label="Nova senha"
86
          type="password"
87
          value={password}
88
          onChangeText={setPassword}
89
          placeholder="Digite uma nova senha"
90
          error={errors.password}
91
          showPasswordToggle
92
        />
93

94
        <Input
95
          label="Confirmar nova senha"
96
          type="password"
97
          value={confirmPassword}
98
          onChangeText={setConfirmPassword}
99
          placeholder="Confirme a nova senha"
100
          error={errors.confirmPassword}
101
          showPasswordToggle
102
        />
103

104
        <Button
105
          title="Trocar senha"
106
          onPress={handleResetPassword}
107
          loading={loading}
108
          style={styles.resetButton}
109
        />
110
      </View>
111
    </AuthScreen>
112
  );
113
}
114

115
const styles = StyleSheet.create({
116
  form: {
117
    marginBottom: 32,
118
  },
119
  resetButton: {
120
    marginTop: 8,
121
  },
122
  link: {
123
    textAlign: 'center',
124
    fontSize: 14,
125
    fontWeight: '500',
126
  },
127
  footer: {
128
    flexDirection: 'row',
129
    justifyContent: 'center',
130
    alignItems: 'center',
131
  },
132
  footerText: {
133
    fontSize: 14,
134
  },
135
});