import React from 'react'; import {RouteProp} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; import { View, Text, Alert, StatusBar, Image, TouchableOpacity, StyleSheet, Keyboard, TouchableWithoutFeedback, } from 'react-native'; import {RootStackParams} from '../routes'; import LinearGradient from 'react-native-linear-gradient'; import LoginInput from '../components/common/LoginInput'; import * as Constants from '../constants'; type LoginScreenRouteProp = RouteProp; type LoginScreenNavigationProp = StackNavigationProp; interface LoginProps { route: LoginScreenRouteProp; navigation: LoginScreenNavigationProp; } const Login = ({navigation}: LoginProps) => { const input_ref = React.createRef(); const [data, setData] = React.useState({ username: '', password: '', isValidUser: true, isValidPassword: true, }); /* Updates the state of username. Also verifies the input of the Username field. */ const handleUsernameUpdate = (val: string) => { let validLength: boolean = val.trim().length >= 6; if (validLength) { setData({ ...data, username: val, isValidUser: true, }); } else { setData({ ...data, username: val, isValidUser: false, }); } }; /* Updates the state of password. Also verifies the input of the Password field. */ const handlePasswordUpdate = (val: string) => { let validLength: boolean = val.trim().length >= 8; if (validLength) { setData({ ...data, password: val, isValidPassword: true, }); } else { setData({ ...data, password: val, isValidPassword: false, }); } }; /* Handler for the Let's Start button or the Go button on the keyboard. Makes a POST request to the Django login API and presents Alerts based on the status codes that the backend returns. */ const handleLogin = async () => { try { if (data.isValidUser && data.isValidPassword) { let response = await fetch(Constants.LOGIN_ENDPOINT, { method: 'POST', body: JSON.stringify({ username: data.username, password: data.password, }), }); let statusCode = response.status; if (statusCode === 200) { Alert.alert('Successfully logged in! 🥳', `Welcome ${data.username}`); } else if (statusCode === 401) { Alert.alert( 'Login failed 😔', 'Try re-entering your login information.', ); } else { Alert.alert( 'Something went wrong! 😭', "Would you believe me if I told you that I don't know what happened?", ); } } } catch (error) { Alert.alert( 'Looks like our servers are down. 😓', "Try again in a couple minutes. We're sorry for the inconvenience.", ); return { name: 'Login error', description: error, }; } }; /* Handler for the submit button on the Username keyboard */ const handleUsernameSubmit = () => { input_ref.current.focus(); }; const handleRegistration = () => { navigation.navigate('Registration'); }; return ( <> { Keyboard.dismiss(); }}> handleUsernameUpdate(user)} onSubmitEditing={() => handleUsernameSubmit()} isValid={data.isValidUser} validationWarning={'Username must be at least 6 characters long.'} /> handlePasswordUpdate(user)} onSubmitEditing={() => handleLogin()} isValid={data.isValidPassword} validationWarning={'Password must be at least 8 characters long.'} input_ref={input_ref} /> Alert.alert("tagg! You're it!")}> Forgot password handleLogin()}> Let's Start! New to tagg?{' '} handleRegistration()}> Get started! ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'transparent', }, linearGradient: { flex: 1, alignItems: 'center', }, logo: { top: 165, width: 215, height: 149, }, forgotPassword: { top: 190, left: -60, }, forgotPasswordText: { fontSize: 15, color: '#FFFFFF', textDecorationLine: 'underline', }, start: { top: 195, width: 144, height: 36, justifyContent: 'center', alignItems: 'center', backgroundColor: '#FFFFFF', borderRadius: 20, marginTop: 15, }, startText: { fontSize: 15, color: '#78A0EF', fontWeight: 'bold', }, getStarted: { color: '#FFFFFF', textDecorationLine: 'underline', }, newUser: { top: 240, color: '#F4DDFF', }, invalidCredentials: { top: 180, color: '#F4DDFF', }, }); export default Login;