Event Planner App using React-Native Expo and Appwrite

Event Planner App using React-Native Expo and Appwrite

#appwrite #AppwriteHackathon

This is a mobile application that has been built using React-Native Expo and Appwrite. When I got to know about this hackathon which was conducted by Hashnode and Appwrite, I was very curious to participate in this. Because I love participating in hackathons and building applications like this and it gives me more knowledge while developing an application I used to do a lot of research and find different libraries for various functionalities to be used in my application.

Initially, when I got to know about Appwrite I thought it might not be better than Firebase as I used it for many of my projects. Even though this was the first application that I had worked with Appwrite I loved this product. It made developers very comfortable by providing many features in their dashboard to use in our application which was super cool 👌!!.


Tech Stack used to build this app:-

  1. React-Native Expo

  2. Appwrite

  3. React-Native-Paper

  4. Expo Linear Gradient

  5. React-Native DateTimePicker

  6. React-Native-Vector-Icons


Before going to the code, watch the demo of the app✌️

Demo Video


Let's get into the app code 👇

  • Initialize the React-Native Expo application

npx create-expo-app@latest --example with-router [appName]

  • Start your application using the below command

npx expo start

  • Install the required dependencies to integrate the app with Appwrite

npm install appwrite

  • Setup the config for using the Appwrite services in your app.

import { Account, Avatars, Client, Databases, ID, Storage } from 'appwrite';

const client = new Client();

client
.setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint  
.setProject(['PROJECT_ID']) // Your project ID);

const account = new Account(client);

const avatars = new Avatars(client);

const databases = new Databases(client);

const storage = new Storage(client);

export { client, databases, account, avatars, storage, ID };

  • Authentication Code -> Login.js

When a user tries to log in he should have an account already otherwise user has to signUp for the application to use the app.

import {
  Alert,
  Button,
  Dimensions,
  ImageBackground,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from "react-native";
import React, { useContext, useState } from "react";
import { SafeAreaView } from "react-native-safe-area-context";
import { Link, useRouter } from "expo-router";
import { LinearGradient } from "expo-linear-gradient";
import { account, client } from "../../appwrite";
import bgImage from "../../assets/event-bgImage1.webp";
import { BlurView } from "expo-blur";

const height = Dimensions.get("screen").height;
const width = Dimensions.get("screen").width;

const login = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const router = useRouter();

  const onLogin = async () => {
    if (!email) {
      return Alert.alert("Please enter an email");
    }
    if (!password) {
      return Alert.alert("Please enter a password");
    }
    console.log("email: " + email);
    console.log("password: " + password);

    return await account
      .createEmailSession(email, password)
      .then((result) => {
        const userAccount = account.get();
        userAccount
          .then(() => {
            router.replace("/home");
          })
          .catch((error) => {
            console.log("error 1st catch: " + error);
          });
      })
      .catch((error) => {
        console.log("error outer login catch: " + error);
        // setUser(null);
        // account.deleteSession('current');
        Alert.alert("Logged Out");
      });
  };

  return (
    <ImageBackground source={bgImage} style={styles.container} blurRadius={2}>
      <LinearGradient
        colors={["rgba(160,40,160,0.8)", "transparent", "rgba(0,0,0,0.7)"]}
        style={styles.background}
      />
      {/* <LinearGradient colors={["rgba(225,225,225,0.9)", "transparent", "rgba(225,225,225,0.9)"]}> */}
      <BlurView style={styles.innerContainer} intensity={120}>
        <TextInput
          placeholder="Email"
          value={email}
          onChangeText={(e) => setEmail(e)}
          style={styles.textInput}
          placeholderTextColor={"black"}
          cursorColor={"black"}
        />
        <TextInput
          placeholder="Password"
          value={password}
          onChangeText={(e) => setPassword(e)}
          style={styles.textInput}
          placeholderTextColor={"black"}
          cursorColor={"black"}
          secureTextEntry={true}
        />
        {/* <Button title='Login' onPress={onSubmitLogin} style={styles.btn}/> */}
        <TouchableOpacity
          style={styles.btn}
          activeOpacity={0.7}
          onPress={onLogin}
        >
          <Text style={styles.btnText}>Login</Text>
        </TouchableOpacity>
        <View style={styles.bottomContainer}>
          <Text>Forgot Password?</Text>
          <Link href={"/signUp"}>
            <Text style={styles.signup}>Sign Up</Text>
          </Link>
        </View>
      {/* </LinearGradient> */}  
      </BlurView> 
    </ImageBackground>
  );
};

export default login;

const styles = StyleSheet.create({
  container: {
    justifyContent: "center",
    alignItems: "center",
    flex: 1,
    resizeMode: "cover",
  },
  background: {
    position: "absolute",
    left: 0,
    right: 0,
    top: 0,
    height: height,
  },
  innerContainer:{
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    width: width/10*9.3,
    marginHorizontal:10,
    paddingVertical: 40,
    borderRadius: 10,
    borderColor: 'black', 
    // borderWidth: 1,
  },
  textInput: {
    // marginHorizontal: 20,
    paddingHorizontal: 8,
    paddingVertical: 10,
    borderWidth: 1,
    borderColor: "black",
    borderRadius: 10,
    marginBottom: 20,
    fontSize: 16,
    width: "94%",
    // backgroundColor: 'skyblue',
  },
  bottomContainer: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-around",
    marginTop: 30,
    width: "100%",
  },
  signup: {
    fontSize: 16,
    fontWeight: "500",
    color: "#9041c2",
  },
  btn: {
    alignItems: "center",
    backgroundColor: "#000000",
    borderRadius: 10,
    width: "50%",
  },
  btnText: {
    fontSize: 16,
    fontWeight: "500",
    color: "#ffffff",
    paddingHorizontal: 20,
    paddingVertical: 10,
  },
});

  • SignUp.js Code

When a user tries to create an account he needs to enter the name, email and password then after submitting he will be automatically redirected to the home tab of the app.

import {
  Alert,
  Button,
  Dimensions,
  ImageBackground,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from "react-native";
import React, { useContext, useState } from "react";
import { SafeAreaView } from "react-native-safe-area-context";
import { Link, useRouter } from "expo-router";
import { LinearGradient } from "expo-linear-gradient";
import { ID, account, client } from "../../appwrite";
import bgImage from "../../assets/event-bgImage1.webp";
import { BlurView } from "expo-blur";

const height = Dimensions.get("screen").height;
const width = Dimensions.get("screen").width;


const signUp = () => {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const router = useRouter();
  const onSignUp = async () => {
    if (!email) {
      return Alert.alert("Please enter an email");
    }
    if (!password) {
      return Alert.alert("Please enter a password");
    }
    if (!name) {
      return Alert.alert("Please enter your name");
    }

    console.log("name: " + name);
    console.log("email: " + email);
    console.log("password: " + password);
    await account.create(ID.unique(), email, password, name);
    return await account
      .createEmailSession(email, password)
      .then((res) => {
        console.log("result signup page: " + res);
        router.replace("/home");
      })
      .catch((error) => {
        console.log("error inside: " + error);
      });
  };

  return (
    <ImageBackground source={bgImage} style={styles.container} blurRadius={2}>
      <LinearGradient
        colors={["rgba(160,40,160,0.8)", "transparent", "rgba(0,0,0,0.7)"]}
        style={styles.background}
      />
      <BlurView style={styles.innerContainer} intensity={160}>
        <TextInput
          placeholder="Name"
          value={name}
          onChangeText={(e) => setName(e)}
          style={styles.textInput}
          placeholderTextColor={"black"}
          cursorColor={"black"}
        />
        <TextInput
          placeholder="Email"
          value={email}
          onChangeText={(e) => setEmail(e)}
          style={styles.textInput}
          placeholderTextColor={"black"}
          cursorColor={"black"}
        />
        <TextInput
          placeholder="Password"
          value={password}
          onChangeText={(e) => setPassword(e)}
          style={styles.textInput}
          placeholderTextColor={"black"}
          cursorColor={"black"}
          secureTextEntry={true}
        />

        <TouchableOpacity
          style={styles.btn}
          activeOpacity={0.7}
          onPress={onSignUp}
        >
          <Text style={styles.btnText}>SignUp</Text>
        </TouchableOpacity>
        <View style={styles.bottomContainer}>
          <Text>Already had an account?</Text>
          <Link href={"/login"}>
            <Text style={styles.signup}>Login</Text>
          </Link>
        </View>
        </BlurView>
    </ImageBackground>
  );
};

export default signUp;

const styles = StyleSheet.create({
  container: {
    justifyContent: "center",
    alignItems: "center",
    flex: 1,
    resizeMode: "cover",
  },
  background: {
    position: "absolute",
    left: 0,
    right: 0,
    top: 0,
    height: height,
  },
  innerContainer: {
    flexDirection: "column",
    alignItems: "center",
    justifyContent: "center",
    width: (width / 10) * 9.3,
    marginHorizontal: 10,
    paddingVertical: 40,
    borderRadius: 10,
    borderColor: "black",
    // borderWidth: 1,
  },
  textInput: {
    // marginHorizontal: 20,
    paddingHorizontal: 8,
    paddingVertical: 10,
    borderWidth: 1,
    borderColor: "black",
    borderRadius: 10,
    marginBottom: 20,
    fontSize: 16,
    width: "94%",
    // backgroundColor: 'skyblue',
  },
  bottomContainer: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-around",
    marginTop: 30,
    width: "100%",
  },
  signup: {
    fontSize: 16,
    fontWeight: "500",
    color: "#9041c2",
  },
  btn: {
    alignItems: "center",
    backgroundColor: "#000000",
    borderRadius: 10,
    width: "50%",
  },
  btnText: {
    fontSize: 16,
    fontWeight: "500",
    color: "#ffffff",
    paddingHorizontal: 20,
    paddingVertical: 10,
  },
});

I added some of the features like event registration, creating an event, and if you are an event organizer then you can update the event details in the app itself whenever you want to make changes. In the myEvents tab, the user can see what are events he was registered for and also what events he created.

  • Challenges Faced while building the application 😥😭

While adding the authentication to the app I faced some issues with the promises while getting the current user data.

Also while updating the event details I faced issues a lot but then I came across the solution and modified the code according to it to resolve the issue.

For the complete code of the application, go through the repository:- Sai1916/EventPlanner (github.com)

Thank you,

Happy Hacking.

Sai Sumedh.