Skip to content

Commit

Permalink
Reset password (#23)
Browse files Browse the repository at this point in the history
* initial screen for reset password.

* add verify code screen.

* add new password screen.

* refactor.

* finish reset password.

* refactor.

* remove comment.
  • Loading branch information
olifer97 authored Jul 18, 2020
1 parent 2b4ee76 commit 5e019da
Show file tree
Hide file tree
Showing 17 changed files with 510 additions and 11 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"react": "16.11.0",
"react-dom": "16.11.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz",
"react-native-confirmation-code-field": "^6.5.0",
"react-native-gesture-handler": "~1.6.0",
"react-native-gifted-chat": "^0.16.3",
"react-native-safe-area-context": "~3.0.7",
Expand Down
3 changes: 2 additions & 1 deletion src/app/components/OkModal/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const styles = StyleSheet.create({
title: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 30
marginBottom: 30,
textAlign: 'center'
},
gif: {
width: 150,
Expand Down
12 changes: 10 additions & 2 deletions src/app/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'react-native-gesture-handler';
import React, { useEffect } from 'react';
import React from 'react';
import { Image } from 'react-native';
import { useSelector } from 'react-redux';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
Expand All @@ -22,6 +21,9 @@ import UploadVideoScreen from '@screens/UploadVideoScreen';
import EditVideoScreen from '@screens/EditVideoScreen';
import TabBarIcon from '@components/TabBarIcon';
import HeaderButtons from '@components/HeaderButtons';
import VerifyCodeScreen from '@screens/ResetPassword/VerifyCodeScreen';
import NewPasswordScreen from '@screens/ResetPassword/NewPasswordScreen';
import ForgotPasswordScreen from '@screens/ResetPassword/ForgotPasswordScreen';

Notifications.setNotificationHandler({
handleNotification: async () => ({
Expand Down Expand Up @@ -120,6 +122,12 @@ export default function App() {
<Stack.Screen name={ROUTES.InitialLoading} component={InitialLoading} />
<Stack.Screen name={ROUTES.Login} component={LoginScreen} />
<Stack.Screen name={ROUTES.SignUp} component={SignUpScreen} />
<Stack.Screen
name={ROUTES.ForgotPassword}
component={ForgotPasswordScreen}
/>
<Stack.Screen name={ROUTES.VerifyCode} component={VerifyCodeScreen} />
<Stack.Screen name={ROUTES.NewPassword} component={NewPasswordScreen} />
<Stack.Screen name={ROUTES.Home} component={WallStackScreen} />
</Stack.Navigator>
</NavigationContainer>
Expand Down
7 changes: 2 additions & 5 deletions src/app/screens/HomeScreen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useDispatch, useSelector } from 'react-redux';
import { SafeAreaView } from 'react-native';
import * as Notifications from 'expo-notifications';

import { ROUTES } from '@constants/routes';
import { registerForPushNotifications } from '@services/NotificationService';
import VideosList from '@components/VideosList';
import actionCreators from '@redux/videos/actions';
Expand All @@ -25,10 +24,8 @@ function HomeScreen({ navigation }) {
console.warn(notification);
});
Notifications.addNotificationResponseReceivedListener((response) => {
const {type, ...data} = response.notification.request.content.data;
const { redirect, payload } = notificationHanlder(
response.notification.request.content.data
)[type];
const { type, ...data } = response.notification.request.content.data;
const { redirect, payload } = notificationHanlder(data)[type];
navigation.navigate(redirect, payload);
});
return () => Notifications.removeAllNotificationListeners();
Expand Down
19 changes: 17 additions & 2 deletions src/app/screens/LoginScreen/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import React, { useCallback, useState, useEffect } from 'react';
import { View, SafeAreaView, TextInput, Text, Image } from 'react-native';
import {
View,
SafeAreaView,
TextInput,
Text,
Image,
TouchableOpacity
} from 'react-native';
import { useDispatch, useSelector } from 'react-redux';

import logo from '@assets/tutubo-03.png';
Expand Down Expand Up @@ -50,6 +57,11 @@ function LoginScreen({ navigation }) {
navigation.navigate(ROUTES.SignUp);
}, [navigation, cleanLogin]);

const onNavigateToResetPassword = useCallback(() => {
cleanLogin();
navigation.navigate(ROUTES.ForgotPassword);
}, [navigation, cleanLogin]);

return (
<SafeAreaView style={styles.container}>
<Image style={styles.logo} source={logo} resizeMode="contain" />
Expand Down Expand Up @@ -86,8 +98,11 @@ function LoginScreen({ navigation }) {
onPress={onNavigateToRegister}
disable={authLoading}
/>
<TouchableOpacity onPress={onNavigateToResetPassword}>
<Text style={styles.forgotPassword}>Olvidaste tu contraseña?</Text>
</TouchableOpacity>
</View>
{error && <Text>{error}</Text>}
{error && <Text style={styles.error}>{error}</Text>}
</SafeAreaView>
);
}
Expand Down
7 changes: 7 additions & 0 deletions src/app/screens/LoginScreen/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ const styles = StyleSheet.create({
},
textDisable: {
color: COLORS.white
},
forgotPassword: {
color: COLORS.main,
textAlign: 'center'
},
error: {
marginTop: 5
}
});

Expand Down
77 changes: 77 additions & 0 deletions src/app/screens/ResetPassword/ForgotPasswordScreen/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React, { useCallback, useState } from 'react';
import { View, SafeAreaView, TextInput, Text } from 'react-native';

import CustomButton from '@components/CustomButton';
import { ROUTES } from '@constants/routes';
import { COLORS } from '@constants/colors';
import { resetPassword } from '@services/AuthService';

import { validateEmail } from '@utils/email';

import styles from './styles';

function ForgotPasswordScreen({ navigation }) {
const [email, setEmail] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');

const emailValid = validateEmail(email);
const disable = !emailValid;

const onEmailSubmit = useCallback(async () => {
setLoading(true);
const response = await resetPassword(email);
if (response.ok) {
navigation.navigate(ROUTES.VerifyCode, { email });
} else {
setError(response.data.reason);
}
setLoading(false);
}, [email, navigation]);

const onNavigateToLogin = useCallback(() => {
navigation.reset({
index: 0,
routes: [{ name: ROUTES.Login }]
});
}, [navigation]);

return (
<SafeAreaView style={styles.container}>
<Text style={styles.title}>Olvidaste tu contraseña?</Text>
<Text style={styles.explanation}>
Para reiniciar tu contraseña ingresa tu email registrado y te enviaremos
un código de verificación.
</Text>
<View>
<TextInput
style={styles.input}
onChangeText={setEmail}
value={email}
label="Email"
placeholder="Email"
keyboardType="email-address"
/>
<CustomButton
text="ENVIAR CÓDIGO"
style={[styles.loginButton, disable && styles.buttonDisable]}
textStyle={disable ? styles.textDisable : styles.loginButtonText}
onPress={onEmailSubmit}
disable={disable}
loading={loading}
loaderColor={COLORS.white}
/>
<CustomButton
text="CANCELAR"
style={styles.loginButton}
textStyle={styles.loginButtonText}
onPress={onNavigateToLogin}
disable={loading}
/>
</View>
{!!error && <Text>{error}</Text>}
</SafeAreaView>
);
}

export default ForgotPasswordScreen;
49 changes: 49 additions & 0 deletions src/app/screens/ResetPassword/ForgotPasswordScreen/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { StyleSheet } from 'react-native';
import { COLORS } from '@constants/colors';

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: COLORS.white
},
title: {
fontSize: 28,
color: COLORS.main
},
explanation: {
margin: 30,
marginTop: 10,
textAlign: 'center',
color: COLORS.gray
},
input: {
backgroundColor: COLORS.white,
borderColor: COLORS.gray,
borderWidth: 1,
borderRadius: 5,
marginBottom: 20,
padding: 5,
width: 200
},
loginButton: {
backgroundColor: COLORS.main,
borderStyle: 'solid',
borderWidth: 1,
borderColor: COLORS.main,
marginBottom: 10
},
buttonDisable: {
borderColor: COLORS.gray,
backgroundColor: COLORS.gray
},
loginButtonText: {
color: COLORS.white
},
textDisable: {
color: COLORS.white
}
});

export default styles;
97 changes: 97 additions & 0 deletions src/app/screens/ResetPassword/NewPasswordScreen/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React, { useCallback, useState } from 'react';
import { View, SafeAreaView, TextInput, Text } from 'react-native';

import CustomButton from '@components/CustomButton';
import OkModal from '@components/OkModal';
import { ROUTES } from '@constants/routes';
import { COLORS } from '@constants/colors';
import { newPassword } from '@services/AuthService';

import styles from './styles';

function NewPasswordScreen({ navigation, route }) {
const [password, setPassword] = useState('');
const [confirmPw, setConfirmPw] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');

const [openModal, setOpenModal] = useState(false);

const email = route?.params?.email;
const code = route?.params?.code;

const disable = !password.length > 0 || password !== confirmPw;

const onNewPasswordSubmit = useCallback(async () => {
setLoading(true);
const response = await newPassword(email, code, password);
if (response.ok) {
setOpenModal(true);
} else {
setError(response.data.reason);
}
setLoading(false);
}, [email, code, password]);

const onCloseModal = useCallback(() => {
setOpenModal(false);
onNavigateToLogin();
}, [onNavigateToLogin]);

const onNavigateToLogin = useCallback(() => {
navigation.reset({
index: 0,
routes: [{ name: ROUTES.Login }]
});
}, [navigation]);

return (
<SafeAreaView style={styles.container}>
<OkModal
text="Se cambió la contraseña correctamente"
closeText="Volver a login"
visible={openModal}
onPress={onCloseModal}
/>
<Text style={styles.title}>Nueva Contraseña</Text>
<Text style={styles.explanation}>Ingresa la nueva contraseña</Text>
<View>
<TextInput
style={styles.input}
onChangeText={setPassword}
value={password}
label="Password"
placeholder="Nueva Contraseña"
secureTextEntry
/>
<TextInput
style={styles.input}
onChangeText={setConfirmPw}
value={confirmPw}
label="Confirm Password"
placeholder="Confirmar Contraseña"
secureTextEntry
/>
<CustomButton
text="CAMBIAR CONTRASEÑA"
style={[styles.loginButton, disable && styles.buttonDisable]}
textStyle={disable ? styles.textDisable : styles.loginButtonText}
onPress={onNewPasswordSubmit}
disable={disable}
loading={loading}
loaderColor={COLORS.white}
/>
<CustomButton
text="CANCELAR"
style={styles.loginButton}
textStyle={styles.loginButtonText}
onPress={onNavigateToLogin}
disable={loading}
/>
</View>
{!!error && <Text>{error}</Text>}
</SafeAreaView>
);
}

export default NewPasswordScreen;
49 changes: 49 additions & 0 deletions src/app/screens/ResetPassword/NewPasswordScreen/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { StyleSheet } from 'react-native';
import { COLORS } from '@constants/colors';

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: COLORS.white
},
title: {
fontSize: 28,
color: COLORS.main
},
explanation: {
margin: 30,
marginTop: 10,
textAlign: 'center',
color: COLORS.gray
},
input: {
backgroundColor: COLORS.white,
borderColor: COLORS.gray,
borderWidth: 1,
borderRadius: 5,
marginBottom: 20,
padding: 5,
width: 200
},
loginButton: {
backgroundColor: COLORS.main,
borderStyle: 'solid',
borderWidth: 1,
borderColor: COLORS.main,
marginBottom: 10
},
buttonDisable: {
borderColor: COLORS.gray,
backgroundColor: COLORS.gray
},
loginButtonText: {
color: COLORS.white
},
textDisable: {
color: COLORS.white
}
});

export default styles;
Loading

0 comments on commit 5e019da

Please sign in to comment.