Giriş Sayfası (Login Page) Firebase – React Native

Mobil uygulamalarda sıklıkla kullanılan giriş sayfası için React Native ile örnek bir sayfa yapacağız.

Arka Plan

İlk sayfa olan giriş sayfamızın görünümü uygulamayı ilk indirenler için çok kıymetlidir. Bu sebeple olabildiğince şık ve sade bir tasarım faydalı olacaktır. Bu sebeple giriş sayfamızın arka planını bir resim ile doldurabiliriz. Bunun için de ImageBackground bileşenini kullanacağız.

Oluşturacağımız arka plan bileşenin içerisinde giriş sayfamızın diğer bileşenleri olacağı için ImageBackground bileşenini kullanarak bu bileşen içerisine sayfanın diğer bileşenlerini ekleyebiliriz.

Arka planınımı bir bileşen olarak (component) oluşturacağız. Bu sebeple Wallpaper.js adında bir dosya oluşturarak alttaki kodları sayfaya yapıştırıyoruz.

import React, {Component} from 'react';
import {StyleSheet, ImageBackground} from 'react-native';

import bgSrc from '../../res/wallpaper.png';

export default class Wallpaper extends Component {
  render() {
    return (
      <ImageBackground style={styles.picture} source={bgSrc}>
        {this.props.children}
      </ImageBackground>
    );
  }
}

const styles = StyleSheet.create({
  picture: {
    flex: 1,
    width: null,
    height: null,
    resizeMode: 'cover',
  },
});

Yukarıdaki kod parçacığında yer alan this.props.children ifadesi bu bileşenin içerisine yerleştirilen diğer bileşenlerin gösterilmesi için kullanılmaktadır.

Metin Alanları (TextInput)

Giriş sayfasında yer alacak bileşenlerden diğeri de kullanıcıların bilgilerini gireceği Form sayfasıdır. Bu sayfada kullanıcı adı (username), mail (email), şifre (password) bilgilerinin yanı sıra beni hatırla (remember me), şifremi unuttum (forgot password) ifadeleri de bulunmaktadır.

Metin alanları için TextInput bileşeni kullanılmaktadır. Uygulamada TextInput değişkenin olması yeni bir durumu oluşturmaktadır. Bu da; kullanıcı metin alanını doldururken cihazın klavyesi açılacaktır. Klavyenin metin alanını kapatmaması için yeni bir bileşen kullanacağız. Bu bileşenimiz KeyboardAwareScrollView bileşenidir. UserInput.js sayfası oluşturup alttaki kodları yapıştırıyoruz.

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
  StyleSheet,
  View,
  TextInput,
  Text,
  Dimensions,
  Image,
} from 'react-native';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import Button from './Button';
import Styles from './Styles';

export default class UserInput extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: '',
      password: '',
      rememberMe: false,
    };
    this.setValues = this.setValues.bind(this);
    this.pressRemember = this.pressRemember.bind(this);
    this.pressForgotPassword = this.pressForgotPassword.bind(this);
  }

  setValues() {
    const {email, password, rememberMe} = this.state;
    const result = {
      email,
      password,
      rememberMe,
    };
    this.props.callBack(result);
  }

  pressRemember() {
    const {rememberMe} = this.state;
    this.setState({rememberMe: !rememberMe});
  }

  pressForgotPassword() {
    this.props.callBackForgotPassword();
  }

  render() {
    const {register = false, forgotPassword = false} = this.props;
    return (
      <KeyboardAwareScrollView
        contentContainerStyle={{padding: 0, margin: 0, height: 100}}>
        <View style={{marginTop: 250}}>
          <View style={styles.inputView}>
            <TextInput
              style={styles.input}
              placeholder="Email"
              returnKeyType="done"
              placeholderTextColor="white"
              underlineColorAndroid="transparent"
              onChangeText={value =>
                this.setState({email: value}, () => this.setValues())
              }
            />
          </View>
            <View style={[styles.inputView, {marginBottom: 0}]}>
              <TextInput
                style={styles.input}
                placeholder='Password'
                secureTextEntry={false}
                returnKeyType="done"
                placeholderTextColor="white"
                underlineColorAndroid="transparent"
                onChangeText={value =>
                  this.setState({password: value}, () => this.setValues())
                }
              />
            </View>
            <View style={{flexDirection: 'row', justifyContent: 'center'}}>
              <Button callBack={this.pressRemember}>
                <View style={Styles.buttonViewSmall}>
                  <Image
                    source={require('../../res/like.png')}
                    style={{
                      color: '#7B53EC',
                      width: 14,
                      height: 12,
                      marginRight: 5,
                    }}
                    resizeMode="stretch"
                  />
                  <Text style={{fontSize: 12, color: 'white'}}>
                    Remember Me
                  </Text>
                </View>
              </Button>
              <Button callBack={this.pressForgotPassword}>
                <View style={Styles.buttonViewSmall}>
                  <Text style={{fontSize: 12, color: '#7B53EC'}}>
                    Forgot Password
                  </Text>
                </View>
              </Button>
            </View>
        </View>
      </KeyboardAwareScrollView>
    );
  }
}

UserInput.propTypes = {
  source: PropTypes.string.isRequired,
  placeholder: PropTypes.string.isRequired,
  secureTextEntry: PropTypes.bool,
  autoCorrect: PropTypes.bool,
  autoCapitalize: PropTypes.string,
  returnKeyType: PropTypes.string,
  password: PropTypes.bool,
  callBackShowPass: PropTypes.func,
  callBack: PropTypes.func,
  register: PropTypes.bool,
  forgotPassword: PropTypes.bool,
  callBackForgotPassword: PropTypes.func,
};

const DEVICE_WIDTH = Dimensions.get('window').width;

const styles = StyleSheet.create({
  inputView: {
    backgroundColor: 'rgba(0,0,0,0.1607843137254902)',
    width: (DEVICE_WIDTH * 2) / 3,
    minHeight: 40,
    marginHorizontal: 20,
    marginBottom: 20,
    paddingLeft: 25,
    borderRadius: 20,
    color: '#ffffff',
  },
  input: {
    width: (DEVICE_WIDTH * 2) / 3,
    height: 40,
    color: 'rgba(0,0,0,0.25098039215686274)',
  },
});

Yukarıdaki kodda yapılan her değişiklik this.props.callback fonksiyonu ile bu bileşeni kullanan sayfaya gönderilmektedir. Şimdi de bu bileşeni kullanacak Form.js sayfasını oluşturalım.

import React, {Component} from 'react';
import {StyleSheet, View} from 'react-native';
import PropTypes from 'prop-types';

import UserInput from './UserInput';

export default class Form extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.setValues = this.setValues.bind(this);
    this.forgotPassword = this.forgotPassword.bind(this);
  }

  setValues(result) {
    const {email, rememberMe, password} = result;
    const LoginData = {
      rememberMe,
      email,
      password,
    };
    this.props.callBack(LoginData);
  }

  forgotPassword() {
    this.props.callBackForgotPassword();
  }

  render() {
    const {register = false, forgotPassword = false} = this.props;
    return (
      <View style={styles.container}>
        <UserInput
          forgotPassword={forgotPassword}
          register={register}
          callBack={this.setValues}
          callBackForgotPassword={this.forgotPassword}
        />
      </View>
    );
  }
}

Form.propTypes = {
  username: PropTypes.string,
  password: PropTypes.string,
  register: PropTypes.bool,
  forgotPassword: PropTypes.bool,
  callBack: PropTypes.func,
  callBackForgotPassword: PropTypes.func,
};

const styles = StyleSheet.create({
  container: {
    flex: 3,
    alignItems: 'center',
    justifyContent: 'flex-end',
  },
});

Yukarıdaki Form bileşenimiz UserInput bileşeninde yapılan değişiklikleri almaktadır. From bileşenimiz aldığı bir değerleri Login.js sayfasına gönderecektir.

Login (Giriş Sayfası)

Giriş sayfamızda öncelikle Wallpaper bileşenimiz oluşturup içerisini Form bileşeni, buttonlar ve uygulama adının yer aldığı bir Text ile dolduralım.

import React, {Component} from 'react';
import {View, Modal, Text} from 'react-native';
import Form from '../components/Form';
import Wallpaper from '../components/Wallpaper';
import AsyncStorage from '@react-native-community/async-storage';
import firebase from 'react-native-firebase';
import Styles from '../components/Styles';
import Uyari from '../components/Uyari';
import Button from '../components/Button';

class Login extends Component {
  constructor() {
    super();
    this.state = {
      isLoading: false,
      checked: false,
      isRemember: false,
      selectedIndex: 0,
      uyariKullanıcıAdi: false,
      uyariBosAlanlar: false,
    };
    this.pressLogin = this.pressLogin.bind(this);
    this.setLoginData = this.setLoginData.bind(this);
    this.openApp = this.openApp.bind(this);
    this.uyariCallBack = this.uyariCallBack.bind(this);
    this.uyariBosAlanlarCallBack = this.uyariBosAlanlarCallBack.bind(this);
    this.openRegister = this.openRegister.bind(this);
    this.openForgotPassword = this.openForgotPassword.bind(this);
  }

  componentDidMount() {}

  async connectToFirebase(email, password, rememberMe) {
    try {
      firebase
        .auth()
        .signInWithEmailAndPassword(email, password)
        .then(credential => {
          if (credential) {
            console.log('Account is exist');
            this.openApp(rememberMe);
          }
        })
        .catch(error => console.log('asdad', error));
    } catch (error) {}
  }

  async saveData() {
    const {LoginData} = this.state;
    const {email, password, rememberMe} = LoginData;
    await AsyncStorage.setItem('@email', email);
    await AsyncStorage.setItem('@password', password);
    await AsyncStorage.setItem('@rememberMe', rememberMe);
  }

  openApp(rememberMe) {
    if (rememberMe) {
      this.saveData();
    }
    this.props.navigation.navigate('CommunityStack');
  }

  openRegister() {
    this.props.navigation.navigate('RegisterStack');
  }

  openForgotPassword() {
    this.props.navigation.navigate('ForgotPasswordStack');
  }

  setLoginData(LoginData) {
    this.setState({LoginData});
  }

  async pressLogin() {
    try {
      const {LoginData} = this.state;
      const {email, password, rememberMe} = LoginData;
      if (this.checkLoginDatas(email) && this.checkLoginDatas(password)) {
        this.connectToFirebase(email, password, rememberMe);
      } else {
        this.setState({uyariBosAlanlar: true});
      }
    } catch (err) {
      this.setState({uyariBosAlanlar: true});
      console.log('errerrerr', err);
    }
  }

  checkLoginDatas(value) {
    if (value !== undefined && value !== null && value.length > 0) {
      return true;
    } else {
      return false;
    }
  }

  uyariCallBack(value) {
    this.setState({uyariKullanıcıAdi: value});
  }

  uyariBosAlanlarCallBack(value) {
    this.setState({uyariBosAlanlar: value});
  }

  render() {
    const {userEmail} = this.state;
    return (
      <Wallpaper>
        <View
          style={{
            marginTop: 100,
            alignItems: 'center',
            justifyContent: 'center',
          }}>
          <Text style={{marginTop: 100, textAlign: 'center'}}>App Name</Text>
        </View>
        <Form
          username={userEmail}
          callBack={this.setLoginData}
          callBackForgotPassword={this.openForgotPassword}
        />
        <View style={{flex: 1, alignItems: 'center'}}>
          <Button callBack={this.pressLogin}>
            <View style={Styles.buttonView}>
              <Text style={{fontSize: 20, color: 'white', fontWeight: 'bold'}}>
                Sign In
              </Text>
            </View>
          </Button>
          <Button callBack={this.openRegister}>
            <View style={Styles.buttonViewTransparent}>
              <Text
                style={{fontSize: 20, color: '#7B53EC', fontWeight: 'bold'}}>
                Sign Up
              </Text>
            </View>
          </Button>
        </View>
        <Modal
          animationType="slide"
          transparent={true}
          visible={this.state.uyariKullanıcıAdi}
          destroyOnClose
          onRequestClose={() => {
            this.setState({uyariKullanıcıAdi: false});
          }}>
          <Uyari
            uyariText="Email ya da şifreniz yanlış girilmiştir."
            callBack={this.uyariCallBack}
          />
        </Modal>
        <Modal
          animationType="slide"
          transparent={true}
          visible={this.state.uyariBosAlanlar}
          destroyOnClose
          onRequestClose={() => {
            this.setState({uyariBosAlanlar: false});
          }}>
          <Uyari
            uyariText="Lütfen bütün alanları eksiksiz doldurun."
            callBack={this.uyariBosAlanlarCallBack}
          />
        </Modal>
      </Wallpaper>
    );
  }
}
export default Login;